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.collections;
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}</code>.
28   * Calling {@link #getCount(Object)} on <code>a</code> would return 2, while
29   * calling {@link #uniqueSet()} would return <code>{a, b, c}</code>.
30   * <p>
31   * <i>NOTE: This interface violates the {@link Collection} contract.</i> 
32   * The behavior specified in many of these methods is <i>not</i> the same
33   * as the behavior specified by <code>Collection</code>.
34   * The noncompliant methods are clearly marked with "(Violation)".
35   * Exercise caution when using a bag as a <code>Collection</code>.
36   * <p>
37   * This violation resulted from the original specification of this interface.
38   * In an ideal world, the interface would be changed to fix the problems, however
39   * it has been decided to maintain backwards compatibility instead.
40   *
41   * @since Commons Collections 2.0
42   * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
43   * 
44   * @author Chuck Burdick
45   * @author Stephen Colebourne
46   */
47  public interface Bag extends Collection {
48  
49      /**
50       * Returns the number of occurrences (cardinality) of the given
51       * object currently in the bag. If the object does not exist in the
52       * bag, return 0.
53       * 
54       * @param object  the object to search for
55       * @return the number of occurrences of the object, zero if not found
56       */
57      int getCount(Object object);
58  
59      /**
60       * <i>(Violation)</i>
61       * Adds one copy the specified object to the Bag.
62       * <p>
63       * If the object is already in the {@link #uniqueSet()} then increment its
64       * count as reported by {@link #getCount(Object)}. Otherwise add it to the
65       * {@link #uniqueSet()} and report its count as 1.
66       * <p>
67       * Since this method always increases the size of the bag,
68       * according to the {@link Collection#add(Object)} contract, it 
69       * should always return <code>true</code>.  Since it sometimes returns
70       * <code>false</code>, this method violates the contract.
71       *
72       * @param object  the object to add
73       * @return <code>true</code> if the object was not already in the <code>uniqueSet</code>
74       */
75      boolean add(Object object);
76  
77      /**
78       * Adds <code>nCopies</code> copies of the specified object to the Bag.
79       * <p>
80       * If the object is already in the {@link #uniqueSet()} then increment its
81       * count as reported by {@link #getCount(Object)}. Otherwise add it to the
82       * {@link #uniqueSet()} and report its count as <code>nCopies</code>.
83       * 
84       * @param object  the object to add
85       * @param nCopies  the number of copies to add
86       * @return <code>true</code> if the object was not already in the <code>uniqueSet</code>
87       */
88      boolean add(Object object, int nCopies);
89  
90      /**
91       * <i>(Violation)</i>
92       * Removes all occurrences of the given object from the bag.
93       * <p>
94       * This will also remove the object from the {@link #uniqueSet()}.
95       * <p>
96       * According to the {@link Collection#remove(Object)} method,
97       * this method should only remove the <i>first</i> occurrence of the
98       * given object, not <i>all</i> occurrences.
99       *
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>&gt;= 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 &gt; 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 }