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