001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.collections4; 018 019import java.util.Collection; 020import java.util.Iterator; 021import java.util.Set; 022 023/** 024 * Defines a collection that counts the number of times an object appears in 025 * the collection. 026 * <p> 027 * Suppose you have a MultiSet that contains {@code {a, a, b, c}}. 028 * Calling {@link #getCount(Object)} on {@code a} would return 2, while 029 * calling {@link #uniqueSet()} would return {@code {a, b, c}}. 030 * </p> 031 * 032 * @param <E> the type held in the multiset 033 * @since 4.1 034 */ 035public interface MultiSet<E> extends Collection<E> { 036 037 /** 038 * An unmodifiable entry for an element and its occurrence as contained in a MultiSet. 039 * <p> 040 * The {@link MultiSet#entrySet()} method returns a view of the multiset whose elements 041 * implement this interface. 042 * 043 * @param <E> the element type 044 */ 045 interface Entry<E> { 046 047 /** 048 * Compares the specified object with this entry for equality. 049 * Returns true if the given object is also a multiset entry 050 * and the two entries represent the same element with the same 051 * number of occurrences. 052 * <p> 053 * More formally, two entries {@code e1} and {@code e2} represent 054 * the same mapping if 055 * <pre> 056 * (e1.getElement()==null ? e2.getElement()==null 057 * : e1.getElement().equals(e2.getElement())) && 058 * (e1.getCount()==e2.getCount()) 059 * </pre> 060 * 061 * @param o object to be compared for equality with this multiset entry 062 * @return true if the specified object is equal to this multiset entry 063 */ 064 @Override 065 boolean equals(Object o); 066 067 /** 068 * Returns the number of occurrences for the element of this entry. 069 * 070 * @return the number of occurrences of the element 071 */ 072 int getCount(); 073 074 /** 075 * Returns the element corresponding to this entry. 076 * 077 * @return the element corresponding to this entry 078 */ 079 E getElement(); 080 081 /** 082 * Returns the hash code value for this multiset entry. 083 * <p> 084 * The hash code of a multiset entry {@code e} is defined to be: 085 * <pre> 086 * (e==null ? 0 : e.hashCode()) ^ noOccurrences) 087 * </pre> 088 * 089 * @return the hash code value for this multiset entry 090 */ 091 @Override 092 int hashCode(); 093 } 094 095 /** 096 * Adds one copy of the specified object to the MultiSet. 097 * <p> 098 * If the object is already in the {@link #uniqueSet()} then increment its 099 * 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}