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       *
43       * @param <E>  the element type
44       */
45      interface Entry<E> {
46  
47          /**
48           * Compares the specified object with this entry for equality.
49           * Returns true if the given object is also a multiset entry
50           * and the two entries represent the same element with the same
51           * number of occurrences.
52           * <p>
53           * More formally, two entries {@code e1} and {@code e2} represent
54           * the same mapping if
55           * <pre>
56           *     (e1.getElement()==null ? e2.getElement()==null
57           *                            : e1.getElement().equals(e2.getElement())) &amp;&amp;
58           *     (e1.getCount()==e2.getCount())
59           * </pre>
60           *
61           * @param o object to be compared for equality with this multiset entry
62           * @return true if the specified object is equal to this multiset entry
63           */
64          @Override
65          boolean equals(Object o);
66  
67          /**
68           * Returns the number of occurrences for the element of this entry.
69           *
70           * @return the number of occurrences of the element
71           */
72          int getCount();
73  
74          /**
75           * Returns the element corresponding to this entry.
76           *
77           * @return the element corresponding to this entry
78           */
79          E getElement();
80  
81          /**
82           * Returns the hash code value for this multiset entry.
83           * <p>
84           * The hash code of a multiset entry {@code e} is defined to be:
85           * <pre>
86           *      (e==null ? 0 : e.hashCode()) ^ noOccurrences)
87           * </pre>
88           *
89           * @return the hash code value for this multiset entry
90           */
91          @Override
92          int hashCode();
93      }
94  
95      /**
96       * Adds one copy of the specified object to the MultiSet.
97       * <p>
98       * If the object is already in the {@link #uniqueSet()} then increment its
99       * count as reported by {@link #getCount(Object)}. Otherwise, add it to the
100      * {@link #uniqueSet()} and report its count as 1.
101      *
102      * @param object  the object to add
103      * @return {@code true} always, as the size of the MultiSet is increased
104      *   in any case
105      */
106     @Override
107     boolean add(E object);
108 
109     /**
110      * Adds a number of occurrences of the specified object to the MultiSet.
111      * <p>
112      * If the object is already in the {@link #uniqueSet()} then increment its
113      * count as reported by {@link #getCount(Object)}. Otherwise, add it to the
114      * {@link #uniqueSet()} and report its count as {@code occurrences}.
115      *
116      * @param object  the object to add
117      * @param occurrences  the number of occurrences to add, may be zero,
118      *   in which case no change is made to the multiset
119      * @return the number of occurrences of the object in the multiset before
120      *   this operation; possibly zero
121      * @throws IllegalArgumentException if occurrences is negative
122      */
123     int add(E object, int occurrences);
124 
125     /**
126      * Returns {@code true} if the MultiSet contains at least one
127      * occurrence for each element contained in the given collection.
128      *
129      * @param coll  the collection to check against
130      * @return {@code true} if the MultiSet contains all the collection
131      */
132     @Override
133     boolean containsAll(Collection<?> coll);
134 
135     /**
136      * Returns a {@link Set} of all entries contained in the MultiSet.
137      * <p>
138      * The returned set is backed by this multiset, so any change to either
139      * is immediately reflected in the other.
140      *
141      * @return the Set of MultiSet entries
142      */
143     Set<Entry<E>> entrySet();
144 
145     /**
146      * Compares this MultiSet to another object.
147      * <p>
148      * This MultiSet equals another object if it is also a MultiSet
149      * that contains the same number of occurrences of the same elements.
150      *
151      * @param obj  the object to compare to
152      * @return true if equal
153      */
154     @Override
155     boolean equals(Object obj);
156 
157     /**
158      * Returns the number of occurrences of the given object currently
159      * in the MultiSet. If the object does not exist in the multiset,
160      * return 0.
161      *
162      * @param object  the object to search for
163      * @return the number of occurrences of the object, zero if not found
164      */
165     int getCount(Object object);
166 
167     /**
168      * Gets a hash code for the MultiSet compatible with the definition of equals.
169      * The hash code is defined as the sum total of a hash code for each element.
170      * The per element hash code is defined as
171      * {@code (e==null ? 0 : e.hashCode()) ^ noOccurrences)}.
172      *
173      * @return the hash code of the MultiSet
174      */
175     @Override
176     int hashCode();
177 
178     /**
179      * Returns an {@link Iterator} over the entire set of members,
180      * including copies due to cardinality. This iterator is fail-fast
181      * and will not tolerate concurrent modifications.
182      *
183      * @return iterator over all elements in the MultiSet
184      */
185     @Override
186     Iterator<E> iterator();
187 
188     /**
189      * Removes one occurrence of the given object from the MultiSet.
190      * <p>
191      * If the number of occurrences after this operation is reduced
192      * to zero, the object will be removed from the {@link #uniqueSet()}.
193      *
194      * @param object  the object to remove
195      * @return {@code true} if this call changed the collection
196      */
197     @Override
198     boolean remove(Object object);
199 
200     /**
201      * Removes a number of occurrences of the specified object from the MultiSet.
202      * <p>
203      * If the number of occurrences to remove is greater than the actual number of
204      * occurrences in the multiset, the object will be removed from the multiset.
205      *
206      * @param object  the object to remove
207      * @param occurrences  the number of occurrences to remove, may be zero,
208      *   in which case no change is made to the multiset
209      * @return the number of occurrences of the object in the multiset
210      *   before the operation; possibly zero
211      * @throws IllegalArgumentException if occurrences is negative
212      */
213     int remove(Object object, int occurrences);
214 
215     /**
216      * Remove all occurrences of all elements from this MultiSet represented
217      * in the given collection.
218      *
219      * @param coll  the collection of elements to remove
220      * @return {@code true} if this call changed the multiset
221      */
222     @Override
223     boolean removeAll(Collection<?> coll);
224 
225     /**
226      * Remove any elements of this MultiSet that are not contained in the
227      * given collection.
228      *
229      * @param coll  the collection of elements to retain
230      * @return {@code true} if this call changed the multiset
231      */
232     @Override
233     boolean retainAll(Collection<?> coll);
234 
235     /**
236      * Sets the number of occurrences of the specified object in the MultiSet
237      * to the given count.
238      * <p>
239      * If the provided count is zero, the object will be removed from the
240      * {@link #uniqueSet()}.
241      *
242      * @param object  the object to update
243      * @param count  the number of occurrences of the object
244      * @return the number of occurrences of the object before this operation, zero
245      *   if the object was not contained in the multiset
246      * @throws IllegalArgumentException if count is negative
247      */
248     int setCount(E object, int count);
249 
250     /**
251      * Returns the total number of items in the MultiSet.
252      *
253      * @return the total size of the multiset
254      */
255     @Override
256     int size();
257 
258     /**
259      * Returns a {@link Set} of unique elements in the MultiSet.
260      * <p>
261      * Uniqueness constraints are the same as those in {@link java.util.Set}.
262      * <p>
263      * The returned set is backed by this multiset, so any change to either
264      * is immediately reflected in the other. Only removal operations are
265      * supported, in which case all occurrences of the element are removed
266      * from the backing multiset.
267      *
268      * @return the Set of unique MultiSet elements
269      */
270     Set<E> uniqueSet();
271 
272 }