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 }