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())) &&
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 * Gets 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 * Gets 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 * Gets 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 }