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