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 */ 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 Bag 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 * <p> 032 * <em>NOTE: This interface violates the {@link Collection} contract.</em> 033 * The behavior specified in many of these methods is <em>not</em> the same 034 * as the behavior specified by {@code Collection}. 035 * The non-compliant methods are clearly marked with "(Violation)". 036 * Exercise caution when using a bag as a {@code Collection}. 037 * </p> 038 * <p> 039 * This violation resulted from the original specification of this interface. 040 * In an ideal world, the interface would be changed to fix the problems, however 041 * it has been decided to maintain backwards compatibility instead. 042 * </p> 043 * <p> 044 * The {@link MultiSet} interface, added in version 4.1, provides the same 045 * functionality while complying with the {@link Collection} contract, and 046 * should be preferred for new code. Existing code can migrate as follows, 047 * with the cardinality-respecting behavior preserved through explicitly 048 * named methods: 049 * </p> 050 * <ul> 051 * <li>{@code bag.add(e)} becomes {@code multiSet.add(e)} 052 * (which always returns {@code true}, per the {@code MultiSet} contract)</li> 053 * <li>{@code bag.getCount(e)} becomes {@code multiSet.getCount(e)}</li> 054 * <li>{@code bag.remove(e)}, which removes all copies, becomes 055 * {@code multiSet.setCount(e, 0)}</li> 056 * <li>{@code bag.containsAll(coll)} becomes 057 * {@code MultiSetUtils.containsOccurrences(multiSet, new HashMultiSet<>(coll))}</li> 058 * <li>{@code bag.removeAll(coll)} becomes 059 * {@code MultiSetUtils.removeOccurrences(multiSet, new HashMultiSet<>(coll))}</li> 060 * <li>{@code bag.retainAll(coll)} becomes 061 * {@code MultiSetUtils.retainOccurrences(multiSet, new HashMultiSet<>(coll))}</li> 062 * <li>{@link SortedBag} and {@code TreeBag} become {@link SortedMultiSet} 063 * and {@code TreeMultiSet}</li> 064 * <li>the {@code CollectionBag} and {@code CollectionSortedBag} wrappers are 065 * not needed, as a {@code MultiSet} already complies with the 066 * {@code Collection} contract</li> 067 * </ul> 068 * 069 * @param <E> The type of elements in this bag 070 * @see MultiSet 071 * @since 2.0 072 * @deprecated Since 4.6.0, use {@link MultiSet} instead; see the migration notes above. 073 */ 074@Deprecated 075public interface Bag<E> extends Collection<E> { 076 077 /** 078 * <em>(Violation)</em> 079 * Adds one copy of the specified object to the Bag. 080 * <p> 081 * If the object is already in the {@link #uniqueSet()} then increment its 082 * count as reported by {@link #getCount(Object)}. Otherwise add it to the 083 * {@link #uniqueSet()} and report its count as 1. 084 * </p> 085 * <p> 086 * Since this method always increases the size of the bag, 087 * according to the {@link Collection#add(Object)} contract, it 088 * should always return {@code true}. Since it sometimes returns 089 * {@code false}, this method violates the contract. 090 * </p> 091 * 092 * @param object The object to add. 093 * @return {@code true} if the object was not already in the {@code uniqueSet}. 094 */ 095 @Override 096 boolean add(E object); 097 098 /** 099 * Adds {@code nCopies} copies of the specified object to the Bag. 100 * <p> 101 * If the object is already in the {@link #uniqueSet()} then increment its 102 * count as reported by {@link #getCount(Object)}. Otherwise add it to the 103 * {@link #uniqueSet()} and report its count as {@code nCopies}. 104 * </p> 105 * 106 * @param object The object to add. 107 * @param nCopies The number of copies to add. 108 * @return {@code true} if the object was not already in the {@code uniqueSet}. 109 * @throws ClassCastException if the class of the specified element prevents it from being added to this collection. 110 */ 111 boolean add(E object, int nCopies); 112 113 /** 114 * <em>(Violation)</em> 115 * Returns {@code true} if the bag contains all elements in 116 * the given collection, respecting cardinality. That is, if the 117 * given collection {@code coll} contains {@code n} copies 118 * of a given object, calling {@link #getCount(Object)} on that object must 119 * be {@code >= n} for all {@code n} in {@code coll}. 120 * 121 * <p> 122 * The {@link Collection#containsAll(Collection)} method specifies 123 * that cardinality should <em>not</em> be respected; this method should 124 * return true if the bag contains at least one of every object contained 125 * in the given collection. 126 * </p> 127 * 128 * @param coll The collection to check against. 129 * @return {@code true} if the Bag contains all the collection. 130 */ 131 @Override 132 boolean containsAll(Collection<?> coll); 133 134 /** 135 * Gets the number of occurrences (cardinality) of the given 136 * object currently in the bag. If the object does not exist in the 137 * bag, return 0. 138 * 139 * @param object The object to search for. 140 * @return The number of occurrences of the object, zero if not found. 141 */ 142 int getCount(Object object); 143 144 /** 145 * Returns an {@link Iterator} over the entire set of members, 146 * including copies due to cardinality. This iterator is fail-fast 147 * and will not tolerate concurrent modifications. 148 * 149 * @return iterator over all elements in the Bag. 150 */ 151 @Override 152 Iterator<E> iterator(); 153 154 /** 155 * <em>(Violation)</em> 156 * Removes all occurrences of the given object from the bag. 157 * <p> 158 * This will also remove the object from the {@link #uniqueSet()}. 159 * </p> 160 * <p> 161 * According to the {@link Collection#remove(Object)} method, 162 * this method should only remove the <em>first</em> occurrence of the 163 * given object, not <em>all</em> occurrences. 164 * </p> 165 * 166 * @param object The object to remove. 167 * @return {@code true} if this call changed the collection. 168 */ 169 @Override 170 boolean remove(Object object); 171 172 /** 173 * Removes {@code nCopies} copies of the specified object from the Bag. 174 * <p> 175 * If the number of copies to remove is greater than the actual number of 176 * copies in the Bag, no error is thrown. 177 * </p> 178 * 179 * @param object The object to remove. 180 * @param nCopies The number of copies to remove. 181 * @return {@code true} if this call changed the collection. 182 */ 183 boolean remove(Object object, int nCopies); 184 185 /** 186 * <em>(Violation)</em> 187 * Remove all elements represented in the given collection, 188 * respecting cardinality. That is, if the given collection 189 * {@code coll} contains {@code n} copies of a given object, 190 * the bag will have {@code n} fewer copies, assuming the bag 191 * had at least {@code n} copies to begin with. 192 * 193 * <p> 194 * The {@link Collection#removeAll(Collection)} method specifies 195 * that cardinality should <em>not</em> be respected; this method should 196 * remove <em>all</em> occurrences of every object contained in the 197 * given collection. 198 * </p> 199 * 200 * @param coll The collection to remove. 201 * @return {@code true} if this call changed the collection. 202 */ 203 @Override 204 boolean removeAll(Collection<?> coll); 205 206 /** 207 * <em>(Violation)</em> 208 * Remove any members of the bag that are not in the given 209 * collection, respecting cardinality. That is, if the given 210 * collection {@code coll} contains {@code n} copies of a 211 * given object and the bag has {@code m > n} copies, then 212 * delete {@code m - n} copies from the bag. In addition, if 213 * {@code e} is an object in the bag but 214 * {@code !coll.contains(e)}, then remove {@code e} and any 215 * of its copies. 216 * 217 * <p> 218 * The {@link Collection#retainAll(Collection)} method specifies 219 * that cardinality should <em>not</em> be respected; this method should 220 * keep <em>all</em> occurrences of every object contained in the 221 * given collection. 222 * </p> 223 * 224 * @param coll The collection to retain. 225 * @return {@code true} if this call changed the collection. 226 */ 227 @Override 228 boolean retainAll(Collection<?> coll); 229 230 /** 231 * Returns the total number of items in the bag across all types. 232 * 233 * @return The total size of the Bag. 234 */ 235 @Override 236 int size(); 237 238 /** 239 * Returns a {@link Set} of unique elements in the Bag. 240 * <p> 241 * Uniqueness constraints are the same as those in {@link Set}. 242 * </p> 243 * 244 * @return The Set of unique Bag elements. 245 */ 246 Set<E> uniqueSet(); 247 248 // The following is not part of the formal Bag interface, however where possible 249 // Bag implementations should follow these comments. 250// /** 251// * Compares this Bag to another. 252// * This Bag equals another Bag if it contains the same number of occurrences of 253// * the same elements. 254// * This equals definition is compatible with the Set interface. 255// * 256// * @param obj The Bag to compare to 257// * @return true if equal 258// */ 259// boolean equals(Object obj); 260// 261// /** 262// * Gets a hash code for the Bag compatible with the definition of equals. 263// * The hash code is defined as the sum total of a hash code for each element. 264// * The per element hash code is defined as 265// * {@code (e==null ? 0 : e.hashCode()) ^ noOccurrences)}. 266// * This hash code definition is compatible with the Set interface. 267// * 268// * @return The hash code of the Bag 269// */ 270// int hashCode(); 271 272}