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 * https://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 */ 017 018package org.apache.commons.collections4; 019 020import java.util.Collection; 021import java.util.Iterator; 022import java.util.Set; 023 024/** 025 * Defines a collection that counts the number of times an object appears in the collection. 026 * <p> 027 * Suppose you have a MultiSet that contains {@code {a, a, b, c}}. Calling {@link #getCount(Object)} on {@code a} would return 2, while calling 028 * {@link #uniqueSet()} would return {@code {a, b, c}}. 029 * </p> 030 * 031 * @param <E> The type held in the multiset 032 * @since 4.1 033 */ 034public interface MultiSet<E> extends Collection<E> { 035 036 /** 037 * An unmodifiable entry for an element and its occurrence as contained in a MultiSet. 038 * <p> 039 * The {@link MultiSet#entrySet()} method returns a view of the multiset whose elements implement this interface. 040 * </p> 041 * 042 * @param <E> the element type 043 */ 044 interface Entry<E> { 045 046 /** 047 * 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 048 * the same element with the same number of occurrences. 049 * <p> 050 * More formally, two entries {@code e1} and {@code e2} represent the same mapping if 051 * </p> 052 * 053 * <pre> 054 * (e1.getElement() == null ? e2.getElement() == null : e1.getElement().equals(e2.getElement())) && (e1.getCount() == e2.getCount()) 055 * </pre> 056 * 057 * @param o object to be compared for equality with this multiset entry. 058 * @return true if the specified object is equal to this multiset entry. 059 */ 060 @Override 061 boolean equals(Object o); 062 063 /** 064 * Gets the number of occurrences for the element of this entry. 065 * 066 * @return The number of occurrences of the element. 067 */ 068 int getCount(); 069 070 /** 071 * Gets the element corresponding to this entry. 072 * 073 * @return The element corresponding to this entry. 074 */ 075 E getElement(); 076 077 /** 078 * Returns the hash code value for this multiset entry. 079 * <p> 080 * The hash code of a multiset entry {@code e} is defined to be: 081 * </p> 082 * 083 * <pre> 084 * (e==null ? 0 : e.hashCode()) ^ noOccurrences) 085 * </pre> 086 * 087 * @return The hash code value for this multiset entry. 088 */ 089 @Override 090 int hashCode(); 091 } 092 093 /** 094 * Adds one copy of the specified object to the MultiSet. 095 * <p> 096 * If the object is already in the {@link #uniqueSet()} then increment its count as reported by {@link #getCount(Object)}. Otherwise, add it to the 097 * {@link #uniqueSet()} and report its count as 1. 098 * </p> 099 * 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}