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 */
017 package org.apache.commons.collections;
018
019 import java.util.Collection;
020 import java.util.Iterator;
021 import 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}</code>.
028 * Calling {@link #getCount(Object)} on <code>a</code> would return 2, while
029 * calling {@link #uniqueSet()} would return <code>{a, b, c}</code>.
030 * <p>
031 * <i>NOTE: This interface violates the {@link Collection} contract.</i>
032 * The behavior specified in many of these methods is <i>not</i> the same
033 * as the behavior specified by <code>Collection</code>.
034 * The noncompliant methods are clearly marked with "(Violation)".
035 * Exercise caution when using a bag as a <code>Collection</code>.
036 * <p>
037 * This violation resulted from the original specification of this interface.
038 * In an ideal world, the interface would be changed to fix the problems, however
039 * it has been decided to maintain backwards compatibility instead.
040 *
041 * @since Commons Collections 2.0
042 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
043 *
044 * @author Chuck Burdick
045 * @author Stephen Colebourne
046 */
047 public interface Bag extends Collection {
048
049 /**
050 * Returns the number of occurrences (cardinality) of the given
051 * object currently in the bag. If the object does not exist in the
052 * bag, return 0.
053 *
054 * @param object the object to search for
055 * @return the number of occurrences of the object, zero if not found
056 */
057 int getCount(Object object);
058
059 /**
060 * <i>(Violation)</i>
061 * Adds one copy the specified object to the Bag.
062 * <p>
063 * If the object is already in the {@link #uniqueSet()} then increment its
064 * count as reported by {@link #getCount(Object)}. Otherwise add it to the
065 * {@link #uniqueSet()} and report its count as 1.
066 * <p>
067 * Since this method always increases the size of the bag,
068 * according to the {@link Collection#add(Object)} contract, it
069 * should always return <code>true</code>. Since it sometimes returns
070 * <code>false</code>, this method violates the contract.
071 *
072 * @param object the object to add
073 * @return <code>true</code> if the object was not already in the <code>uniqueSet</code>
074 */
075 boolean add(Object object);
076
077 /**
078 * Adds <code>nCopies</code> copies of the specified object to the Bag.
079 * <p>
080 * If the object is already in the {@link #uniqueSet()} then increment its
081 * count as reported by {@link #getCount(Object)}. Otherwise add it to the
082 * {@link #uniqueSet()} and report its count as <code>nCopies</code>.
083 *
084 * @param object the object to add
085 * @param nCopies the number of copies to add
086 * @return <code>true</code> if the object was not already in the <code>uniqueSet</code>
087 */
088 boolean add(Object object, int nCopies);
089
090 /**
091 * <i>(Violation)</i>
092 * Removes all occurrences of the given object from the bag.
093 * <p>
094 * This will also remove the object from the {@link #uniqueSet()}.
095 * <p>
096 * According to the {@link Collection#remove(Object)} method,
097 * this method should only remove the <i>first</i> occurrence of the
098 * given object, not <i>all</i> occurrences.
099 *
100 * @return <code>true</code> if this call changed the collection
101 */
102 boolean remove(Object object);
103
104 /**
105 * Removes <code>nCopies</code> copies of the specified object from the Bag.
106 * <p>
107 * If the number of copies to remove is greater than the actual number of
108 * copies in the Bag, no error is thrown.
109 *
110 * @param object the object to remove
111 * @param nCopies the number of copies to remove
112 * @return <code>true</code> if this call changed the collection
113 */
114 boolean remove(Object object, int nCopies);
115
116 /**
117 * Returns a {@link Set} of unique elements in the Bag.
118 * <p>
119 * Uniqueness constraints are the same as those in {@link java.util.Set}.
120 *
121 * @return the Set of unique Bag elements
122 */
123 Set uniqueSet();
124
125 /**
126 * Returns the total number of items in the bag across all types.
127 *
128 * @return the total size of the Bag
129 */
130 int size();
131
132 /**
133 * <i>(Violation)</i>
134 * Returns <code>true</code> if the bag contains all elements in
135 * the given collection, respecting cardinality. That is, if the
136 * given collection <code>coll</code> contains <code>n</code> copies
137 * of a given object, calling {@link #getCount(Object)} on that object must
138 * be <code>>= n</code> for all <code>n</code> in <code>coll</code>.
139 * <p>
140 * The {@link Collection#containsAll(Collection)} method specifies
141 * that cardinality should <i>not</i> be respected; this method should
142 * return true if the bag contains at least one of every object contained
143 * in the given collection.
144 *
145 * @param coll the collection to check against
146 * @return <code>true</code> if the Bag contains all the collection
147 */
148 boolean containsAll(Collection coll);
149
150 /**
151 * <i>(Violation)</i>
152 * Remove all elements represented in the given collection,
153 * respecting cardinality. That is, if the given collection
154 * <code>coll</code> contains <code>n</code> copies of a given object,
155 * the bag will have <code>n</code> fewer copies, assuming the bag
156 * had at least <code>n</code> copies to begin with.
157 *
158 * <P>The {@link Collection#removeAll(Collection)} method specifies
159 * that cardinality should <i>not</i> be respected; this method should
160 * remove <i>all</i> occurrences of every object contained in the
161 * given collection.
162 *
163 * @param coll the collection to remove
164 * @return <code>true</code> if this call changed the collection
165 */
166 boolean removeAll(Collection coll);
167
168 /**
169 * <i>(Violation)</i>
170 * Remove any members of the bag that are not in the given
171 * collection, respecting cardinality. That is, if the given
172 * collection <code>coll</code> contains <code>n</code> copies of a
173 * given object and the bag has <code>m > n</code> copies, then
174 * delete <code>m - n</code> copies from the bag. In addition, if
175 * <code>e</code> is an object in the bag but
176 * <code>!coll.contains(e)</code>, then remove <code>e</code> and any
177 * of its copies.
178 *
179 * <P>The {@link Collection#retainAll(Collection)} method specifies
180 * that cardinality should <i>not</i> be respected; this method should
181 * keep <i>all</i> occurrences of every object contained in the
182 * given collection.
183 *
184 * @param coll the collection to retain
185 * @return <code>true</code> if this call changed the collection
186 */
187 boolean retainAll(Collection coll);
188
189 /**
190 * Returns an {@link Iterator} over the entire set of members,
191 * including copies due to cardinality. This iterator is fail-fast
192 * and will not tolerate concurrent modifications.
193 *
194 * @return iterator over all elements in the Bag
195 */
196 Iterator iterator();
197
198 // The following is not part of the formal Bag interface, however where possible
199 // Bag implementations should follow these comments.
200 // /**
201 // * Compares this Bag to another.
202 // * This Bag equals another Bag if it contains the same number of occurrences of
203 // * the same elements.
204 // * This equals definition is compatible with the Set interface.
205 // *
206 // * @param obj the Bag to compare to
207 // * @return true if equal
208 // */
209 // boolean equals(Object obj);
210 //
211 // /**
212 // * Gets a hash code for the Bag compatible with the definition of equals.
213 // * The hash code is defined as the sum total of a hash code for each element.
214 // * The per element hash code is defined as
215 // * <code>(e==null ? 0 : e.hashCode()) ^ noOccurances)</code>.
216 // * This hash code definition is compatible with the Set interface.
217 // *
218 // * @return the hash code of the Bag
219 // */
220 // int hashCode();
221
222 }