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 * 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 }