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 */ 017package org.apache.commons.collections4; 018 019import java.util.Collection; 020import java.util.Iterator; 021import 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 * @param <E> the type held in the bag 042 * @since 2.0 043 * @version $Id: Bag.html 972421 2015-11-14 20:00:04Z tn $ 044 */ 045public interface Bag<E> extends Collection<E> { 046 047 /** 048 * Returns the number of occurrences (cardinality) of the given 049 * object currently in the bag. If the object does not exist in the 050 * bag, return 0. 051 * 052 * @param object the object to search for 053 * @return the number of occurrences of the object, zero if not found 054 */ 055 int getCount(Object object); 056 057 /** 058 * <i>(Violation)</i> 059 * Adds one copy of the specified object to the Bag. 060 * <p> 061 * If the object is already in the {@link #uniqueSet()} then increment its 062 * count as reported by {@link #getCount(Object)}. Otherwise add it to the 063 * {@link #uniqueSet()} and report its count as 1. 064 * <p> 065 * Since this method always increases the size of the bag, 066 * according to the {@link Collection#add(Object)} contract, it 067 * should always return <code>true</code>. Since it sometimes returns 068 * <code>false</code>, this method violates the contract. 069 * 070 * @param object the object to add 071 * @return <code>true</code> if the object was not already in the <code>uniqueSet</code> 072 */ 073 boolean add(E object); 074 075 /** 076 * Adds <code>nCopies</code> copies of the specified object to the Bag. 077 * <p> 078 * If the object is already in the {@link #uniqueSet()} then increment its 079 * count as reported by {@link #getCount(Object)}. Otherwise add it to the 080 * {@link #uniqueSet()} and report its count as <code>nCopies</code>. 081 * 082 * @param object the object to add 083 * @param nCopies the number of copies to add 084 * @return <code>true</code> if the object was not already in the <code>uniqueSet</code> 085 */ 086 boolean add(E object, int nCopies); 087 088 /** 089 * <i>(Violation)</i> 090 * Removes all occurrences of the given object from the bag. 091 * <p> 092 * This will also remove the object from the {@link #uniqueSet()}. 093 * <p> 094 * According to the {@link Collection#remove(Object)} method, 095 * this method should only remove the <i>first</i> occurrence of the 096 * given object, not <i>all</i> occurrences. 097 * 098 * @param object the object to remove 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<E> 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<E> 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}