View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4;
18  
19  import java.util.Collection;
20  import java.util.Iterator;
21  import java.util.Set;
22  
23  /**
24   * Defines a collection that counts the number of times an object appears in
25   * the collection.
26   * <p>
27   * Suppose you have a MultiSet that contains {@code {a, a, b, c}}.
28   * Calling {@link #getCount(Object)} on {@code a} would return 2, while
29   * calling {@link #uniqueSet()} would return {@code {a, b, c}}.
30   * </p>
31   *
32   * @param <E> the type held in the multiset
33   * @since 4.1
34   */
35  public interface MultiSet<E> extends Collection<E> {
36  
37      /**
38       * An unmodifiable entry for an element and its occurrence as contained in a MultiSet.
39       * <p>
40       * The {@link MultiSet#entrySet()} method returns a view of the multiset whose elements
41       * implement this interface.
42       * </p>
43       *
44       * @param <E>  the element type
45       */
46      interface Entry<E> {
47  
48          /**
49           * Compares the specified object with this entry for equality.
50           * Returns true if the given object is also a multiset entry
51           * and the two entries represent the same element with the same
52           * number of occurrences.
53           * <p>
54           * More formally, two entries {@code e1} and {@code e2} represent
55           * the same mapping if
56           * </p>
57           * <pre>
58           *     (e1.getElement()==null ? e2.getElement()==null
59           *                            : e1.getElement().equals(e2.getElement())) &amp;&amp;
60           *     (e1.getCount()==e2.getCount())
61           * </pre>
62           *
63           * @param o object to be compared for equality with this multiset entry
64           * @return true if the specified object is equal to this multiset entry
65           */
66          @Override
67          boolean equals(Object o);
68  
69          /**
70           * Returns the number of occurrences for the element of this entry.
71           *
72           * @return the number of occurrences of the element
73           */
74          int getCount();
75  
76          /**
77           * Returns the element corresponding to this entry.
78           *
79           * @return the element corresponding to this entry
80           */
81          E getElement();
82  
83          /**
84           * Returns the hash code value for this multiset entry.
85           * <p>
86           * The hash code of a multiset entry {@code e} is defined to be:
87           * <pre>
88           *      (e==null ? 0 : e.hashCode()) ^ noOccurrences)
89           * </pre>
90           *
91           * @return the hash code value for this multiset entry
92           */
93          @Override
94          int hashCode();
95      }
96  
97      /**
98       * Adds one copy of the specified object to the MultiSet.
99       * <p>
100      * If the object is already in the {@link #uniqueSet()} then increment its
101      * count as reported by {@link #getCount(Object)}. Otherwise, add it to the
102      * {@link #uniqueSet()} and report its count as 1.
103      * </p>
104      *
105      * @param object  the object to add
106      * @return {@code true} always, as the size of the MultiSet is increased
107      *   in any case
108      */
109     @Override
110     boolean add(E object);
111 
112     /**
113      * Adds a number of occurrences of the specified object to the MultiSet.
114      * <p>
115      * If the object is already in the {@link #uniqueSet()} then increment its
116      * count as reported by {@link #getCount(Object)}. Otherwise, add it to the
117      * {@link #uniqueSet()} and report its count as {@code occurrences}.
118      * </p>
119      *
120      * @param object  the object to add
121      * @param occurrences  the number of occurrences to add, may be zero,
122      *   in which case no change is made to the multiset
123      * @return the number of occurrences of the object in the multiset before
124      *   this operation; possibly zero
125      * @throws IllegalArgumentException if occurrences is negative
126      */
127     int add(E object, int occurrences);
128 
129     /**
130      * Returns {@code true} if the MultiSet contains at least one
131      * occurrence for each element contained in the given collection.
132      *
133      * @param coll  the collection to check against
134      * @return {@code true} if the MultiSet contains all the collection
135      */
136     @Override
137     boolean containsAll(Collection<?> coll);
138 
139     /**
140      * Returns a {@link Set} of all entries contained in the MultiSet.
141      * <p>
142      * The returned set is backed by this multiset, so any change to either
143      * is immediately reflected in the other.
144      * </p>
145      *
146      * @return the Set of MultiSet entries
147      */
148     Set<Entry<E>> entrySet();
149 
150     /**
151      * Compares this MultiSet to another object.
152      * <p>
153      * This MultiSet equals another object if it is also a MultiSet
154      * that contains the same number of occurrences of the same elements.
155      * </p>
156      *
157      * @param obj  the object to compare to
158      * @return true if equal
159      */
160     @Override
161     boolean equals(Object obj);
162 
163     /**
164      * Returns the number of occurrences of the given object currently
165      * in the MultiSet. If the object does not exist in the multiset,
166      * return 0.
167      *
168      * @param object  the object to search for
169      * @return the number of occurrences of the object, zero if not found
170      */
171     int getCount(Object object);
172 
173     /**
174      * Gets a hash code for the MultiSet compatible with the definition of equals.
175      * The hash code is defined as the sum total of a hash code for each element.
176      * The per element hash code is defined as
177      * {@code (e==null ? 0 : e.hashCode()) ^ noOccurrences)}.
178      *
179      * @return the hash code of the MultiSet
180      */
181     @Override
182     int hashCode();
183 
184     /**
185      * Returns an {@link Iterator} over the entire set of members,
186      * including copies due to cardinality. This iterator is fail-fast
187      * and will not tolerate concurrent modifications.
188      *
189      * @return iterator over all elements in the MultiSet
190      */
191     @Override
192     Iterator<E> iterator();
193 
194     /**
195      * Removes one occurrence of the given object from the MultiSet.
196      * <p>
197      * If the number of occurrences after this operation is reduced
198      * to zero, the object will be removed from the {@link #uniqueSet()}.
199      *
200      * @param object  the object to remove
201      * @return {@code true} if this call changed the collection
202      */
203     @Override
204     boolean remove(Object object);
205 
206     /**
207      * Removes a number of occurrences of the specified object from the MultiSet.
208      * <p>
209      * If the number of occurrences to remove is greater than the actual number of
210      * occurrences in the multiset, the object will be removed from the multiset.
211      * </p>
212      *
213      * @param object  the object to remove
214      * @param occurrences  the number of occurrences to remove, may be zero,
215      *   in which case no change is made to the multiset
216      * @return the number of occurrences of the object in the multiset
217      *   before the operation; possibly zero
218      * @throws IllegalArgumentException if occurrences is negative
219      */
220     int remove(Object object, int occurrences);
221 
222     /**
223      * Remove all occurrences of all elements from this MultiSet represented
224      * in the given collection.
225      *
226      * @param coll  the collection of elements to remove
227      * @return {@code true} if this call changed the multiset
228      */
229     @Override
230     boolean removeAll(Collection<?> coll);
231 
232     /**
233      * Remove any elements of this MultiSet that are not contained in the
234      * given collection.
235      *
236      * @param coll  the collection of elements to retain
237      * @return {@code true} if this call changed the multiset
238      */
239     @Override
240     boolean retainAll(Collection<?> coll);
241 
242     /**
243      * Sets the number of occurrences of the specified object in the MultiSet
244      * to the given count.
245      * <p>
246      * If the provided count is zero, the object will be removed from the
247      * {@link #uniqueSet()}.
248      * </p>
249      *
250      * @param object  the object to update
251      * @param count  the number of occurrences of the object
252      * @return the number of occurrences of the object before this operation, zero
253      *   if the object was not contained in the multiset
254      * @throws IllegalArgumentException if count is negative
255      */
256     int setCount(E object, int count);
257 
258     /**
259      * Returns the total number of items in the MultiSet.
260      *
261      * @return the total size of the multiset
262      */
263     @Override
264     int size();
265 
266     /**
267      * Returns a {@link Set} of unique elements in the MultiSet.
268      * <p>
269      * Uniqueness constraints are the same as those in {@link java.util.Set}.
270      * </p>
271      * <p>
272      * The returned set is backed by this multiset, so any change to either
273      * is immediately reflected in the other. Only removal operations are
274      * supported, in which case all occurrences of the element are removed
275      * from the backing multiset.
276      * </p>
277      *
278      * @return the Set of unique MultiSet elements
279      */
280     Set<E> uniqueSet();
281 
282 }