View Javadoc
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 Bag 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   * <p>
32   * <em>NOTE: This interface violates the {@link Collection} contract.</em>
33   * The behavior specified in many of these methods is <em>not</em> the same
34   * as the behavior specified by {@code Collection}.
35   * The non-compliant methods are clearly marked with "(Violation)".
36   * Exercise caution when using a bag as a {@code Collection}.
37   * </p>
38   * <p>
39   * This violation resulted from the original specification of this interface.
40   * In an ideal world, the interface would be changed to fix the problems, however
41   * it has been decided to maintain backwards compatibility instead.
42   * </p>
43   *
44   * @param <E> the type of elements in this bag
45   * @since 2.0
46   */
47  public interface Bag<E> extends Collection<E> {
48  
49      /**
50       * <em>(Violation)</em>
51       * Adds one copy of the specified object to the Bag.
52       * <p>
53       * If the object is already in the {@link #uniqueSet()} then increment its
54       * count as reported by {@link #getCount(Object)}. Otherwise add it to the
55       * {@link #uniqueSet()} and report its count as 1.
56       * </p>
57       * <p>
58       * Since this method always increases the size of the bag,
59       * according to the {@link Collection#add(Object)} contract, it
60       * should always return {@code true}.  Since it sometimes returns
61       * {@code false}, this method violates the contract.
62       * </p>
63       *
64       * @param object  the object to add
65       * @return {@code true} if the object was not already in the {@code uniqueSet}
66       */
67      @Override
68      boolean add(E object);
69  
70      /**
71       * Adds {@code nCopies} copies of the specified object to the Bag.
72       * <p>
73       * If the object is already in the {@link #uniqueSet()} then increment its
74       * count as reported by {@link #getCount(Object)}. Otherwise add it to the
75       * {@link #uniqueSet()} and report its count as {@code nCopies}.
76       * </p>
77       *
78       * @param object  the object to add
79       * @param nCopies  the number of copies to add
80       * @return {@code true} if the object was not already in the {@code uniqueSet}
81       * @throws ClassCastException if the class of the specified element prevents it from being added to this collection
82       */
83      boolean add(E object, int nCopies);
84  
85      /**
86       * <em>(Violation)</em>
87       * Returns {@code true} if the bag contains all elements in
88       * the given collection, respecting cardinality.  That is, if the
89       * given collection {@code coll} contains {@code n} copies
90       * of a given object, calling {@link #getCount(Object)} on that object must
91       * be {@code &gt;= n} for all {@code n} in {@code coll}.
92       *
93       * <p>
94       * The {@link Collection#containsAll(Collection)} method specifies
95       * that cardinality should <em>not</em> be respected; this method should
96       * return true if the bag contains at least one of every object contained
97       * in the given collection.
98       * </p>
99       *
100      * @param coll  the collection to check against
101      * @return {@code true} if the Bag contains all the collection
102      */
103     @Override
104     boolean containsAll(Collection<?> coll);
105 
106     /**
107      * Returns the number of occurrences (cardinality) of the given
108      * object currently in the bag. If the object does not exist in the
109      * bag, return 0.
110      *
111      * @param object  the object to search for
112      * @return the number of occurrences of the object, zero if not found
113      */
114     int getCount(Object object);
115 
116     /**
117      * Returns an {@link Iterator} over the entire set of members,
118      * including copies due to cardinality. This iterator is fail-fast
119      * and will not tolerate concurrent modifications.
120      *
121      * @return iterator over all elements in the Bag
122      */
123     @Override
124     Iterator<E> iterator();
125 
126     /**
127      * <em>(Violation)</em>
128      * Removes all occurrences of the given object from the bag.
129      * <p>
130      * This will also remove the object from the {@link #uniqueSet()}.
131      * </p>
132      * <p>
133      * According to the {@link Collection#remove(Object)} method,
134      * this method should only remove the <em>first</em> occurrence of the
135      * given object, not <em>all</em> occurrences.
136      * </p>
137      *
138      * @param object  the object to remove
139      * @return {@code true} if this call changed the collection
140      */
141     @Override
142     boolean remove(Object object);
143 
144     /**
145      * Removes {@code nCopies} copies of the specified object from the Bag.
146      * <p>
147      * If the number of copies to remove is greater than the actual number of
148      * copies in the Bag, no error is thrown.
149      * </p>
150      *
151      * @param object  the object to remove
152      * @param nCopies  the number of copies to remove
153      * @return {@code true} if this call changed the collection
154      */
155     boolean remove(Object object, int nCopies);
156 
157     /**
158      * <em>(Violation)</em>
159      * Remove all elements represented in the given collection,
160      * respecting cardinality.  That is, if the given collection
161      * {@code coll} contains {@code n} copies of a given object,
162      * the bag will have {@code n} fewer copies, assuming the bag
163      * had at least {@code n} copies to begin with.
164      *
165      * <p>
166      * The {@link Collection#removeAll(Collection)} method specifies
167      * that cardinality should <em>not</em> be respected; this method should
168      * remove <em>all</em> occurrences of every object contained in the
169      * given collection.
170      * </p>
171      *
172      * @param coll  the collection to remove
173      * @return {@code true} if this call changed the collection
174      */
175     @Override
176     boolean removeAll(Collection<?> coll);
177 
178     /**
179      * <em>(Violation)</em>
180      * Remove any members of the bag that are not in the given
181      * collection, respecting cardinality.  That is, if the given
182      * collection {@code coll} contains {@code n} copies of a
183      * given object and the bag has {@code m &gt; n} copies, then
184      * delete {@code m - n} copies from the bag.  In addition, if
185      * {@code e} is an object in the bag but
186      * {@code !coll.contains(e)}, then remove {@code e} and any
187      * of its copies.
188      *
189      * <p>
190      * The {@link Collection#retainAll(Collection)} method specifies
191      * that cardinality should <em>not</em> be respected; this method should
192      * keep <em>all</em> occurrences of every object contained in the
193      * given collection.
194      * </p>
195      *
196      * @param coll  the collection to retain
197      * @return {@code true} if this call changed the collection
198      */
199     @Override
200     boolean retainAll(Collection<?> coll);
201 
202     /**
203      * Returns the total number of items in the bag across all types.
204      *
205      * @return the total size of the Bag
206      */
207     @Override
208     int size();
209 
210     /**
211      * Returns a {@link Set} of unique elements in the Bag.
212      * <p>
213      * Uniqueness constraints are the same as those in {@link java.util.Set}.
214      * </p>
215      *
216      * @return the Set of unique Bag elements
217      */
218     Set<E> uniqueSet();
219 
220     // The following is not part of the formal Bag interface, however where possible
221     // Bag implementations should follow these comments.
222 //    /**
223 //     * Compares this Bag to another.
224 //     * This Bag equals another Bag if it contains the same number of occurrences of
225 //     * the same elements.
226 //     * This equals definition is compatible with the Set interface.
227 //     *
228 //     * @param obj  the Bag to compare to
229 //     * @return true if equal
230 //     */
231 //    boolean equals(Object obj);
232 //
233 //    /**
234 //     * Gets a hash code for the Bag compatible with the definition of equals.
235 //     * The hash code is defined as the sum total of a hash code for each element.
236 //     * The per element hash code is defined as
237 //     * {@code (e==null ? 0 : e.hashCode()) ^ noOccurrences)}.
238 //     * This hash code definition is compatible with the Set interface.
239 //     *
240 //     * @return the hash code of the Bag
241 //     */
242 //    int hashCode();
243 
244 }