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