    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 *      https://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}}.
    028 * Calling {@link #getCount(Object)} on {@code a} would return 2, while
    029 * calling {@link #uniqueSet()} would return {@code {a, b, c}}.
    030 * </p>
    031 * <p>
    032 * <em>NOTE: This interface violates the {@link Collection} contract.</em>
    033 * The behavior specified in many of these methods is <em>not</em> the same
    034 * as the behavior specified by {@code Collection}.
    035 * The non-compliant methods are clearly marked with "(Violation)".
    036 * Exercise caution when using a bag as a {@code Collection}.
    037 * </p>
    038 * <p>
    039 * This violation resulted from the original specification of this interface.
    040 * In an ideal world, the interface would be changed to fix the problems, however
    041 * it has been decided to maintain backwards compatibility instead.
    042 * </p>
    043 * <p>
    044 * The {@link MultiSet} interface, added in version 4.1, provides the same
    045 * functionality while complying with the {@link Collection} contract, and
    046 * should be preferred for new code. Existing code can migrate as follows,
    047 * with the cardinality-respecting behavior preserved through explicitly
    048 * named methods:
    049 * </p>
    050 * <ul>
    051 *   <li>{@code bag.add(e)} becomes {@code multiSet.add(e)}
    052 *       (which always returns {@code true}, per the {@code MultiSet} contract)</li>
    053 *   <li>{@code bag.getCount(e)} becomes {@code multiSet.getCount(e)}</li>
    054 *   <li>{@code bag.remove(e)}, which removes all copies, becomes
    055 *       {@code multiSet.setCount(e, 0)}</li>
    056 *   <li>{@code bag.containsAll(coll)} becomes
    057 *       {@code MultiSetUtils.containsOccurrences(multiSet, new HashMultiSet<>(coll))}</li>
    058 *   <li>{@code bag.removeAll(coll)} becomes
    059 *       {@code MultiSetUtils.removeOccurrences(multiSet, new HashMultiSet<>(coll))}</li>
    060 *   <li>{@code bag.retainAll(coll)} becomes
    061 *       {@code MultiSetUtils.retainOccurrences(multiSet, new HashMultiSet<>(coll))}</li>
    062 *   <li>{@link SortedBag} and {@code TreeBag} become {@link SortedMultiSet}
    063 *       and {@code TreeMultiSet}</li>
    064 *   <li>the {@code CollectionBag} and {@code CollectionSortedBag} wrappers are
    065 *       not needed, as a {@code MultiSet} already complies with the
    066 *       {@code Collection} contract</li>
    067 * </ul>
    068 *
    069 * @param <E> The type of elements in this bag
    070 * @see MultiSet
    071 * @since 2.0
    072 * @deprecated Since 4.6.0, use {@link MultiSet} instead; see the migration notes above.
    073 */
    074@Deprecated
    075public interface Bag<E> extends Collection<E> {
    076
    077    /**
    078     * <em>(Violation)</em>
    079     * Adds one copy of the specified object to the Bag.
    080     * <p>
    081     * If the object is already in the {@link #uniqueSet()} then increment its
    082     * count as reported by {@link #getCount(Object)}. Otherwise add it to the
    083     * {@link #uniqueSet()} and report its count as 1.
    084     * </p>
    085     * <p>
    086     * Since this method always increases the size of the bag,
    087     * according to the {@link Collection#add(Object)} contract, it
    088     * should always return {@code true}. Since it sometimes returns
    089     * {@code false}, this method violates the contract.
    090     * </p>
    091     *
    092     * @param object  The object to add.
    093     * @return {@code true} if the object was not already in the {@code uniqueSet}.
    094     */
    095    @Override
    096    boolean add(E object);
    097
    098    /**
    099     * Adds {@code nCopies} copies of the specified object to the Bag.
    100     * <p>
    101     * If the object is already in the {@link #uniqueSet()} then increment its
    102     * count as reported by {@link #getCount(Object)}. Otherwise add it to the
    103     * {@link #uniqueSet()} and report its count as {@code nCopies}.
    104     * </p>
    105     *
    106     * @param object  The object to add.
    107     * @param nCopies  The number of copies to add.
    108     * @return {@code true} if the object was not already in the {@code uniqueSet}.
    109     * @throws ClassCastException if the class of the specified element prevents it from being added to this collection.
    110     */
    111    boolean add(E object, int nCopies);
    112
    113    /**
    114     * <em>(Violation)</em>
    115     * Returns {@code true} if the bag contains all elements in
    116     * the given collection, respecting cardinality. That is, if the
    117     * given collection {@code coll} contains {@code n} copies
    118     * of a given object, calling {@link #getCount(Object)} on that object must
    119     * be {@code &gt;= n} for all {@code n} in {@code coll}.
    120     *
    121     * <p>
    122     * The {@link Collection#containsAll(Collection)} method specifies
    123     * that cardinality should <em>not</em> be respected; this method should
    124     * return true if the bag contains at least one of every object contained
    125     * in the given collection.
    126     * </p>
    127     *
    128     * @param coll  The collection to check against.
    129     * @return {@code true} if the Bag contains all the collection.
    130     */
    131    @Override
    132    boolean containsAll(Collection<?> coll);
    133
    134    /**
    135     * Gets the number of occurrences (cardinality) of the given
    136     * object currently in the bag. If the object does not exist in the
    137     * bag, return 0.
    138     *
    139     * @param object  The object to search for.
    140     * @return The number of occurrences of the object, zero if not found.
    141     */
    142    int getCount(Object object);
    143
    144    /**
    145     * Returns an {@link Iterator} over the entire set of members,
    146     * including copies due to cardinality. This iterator is fail-fast
    147     * and will not tolerate concurrent modifications.
    148     *
    149     * @return iterator over all elements in the Bag.
    150     */
    151    @Override
    152    Iterator<E> iterator();
    153
    154    /**
    155     * <em>(Violation)</em>
    156     * Removes all occurrences of the given object from the bag.
    157     * <p>
    158     * This will also remove the object from the {@link #uniqueSet()}.
    159     * </p>
    160     * <p>
    161     * According to the {@link Collection#remove(Object)} method,
    162     * this method should only remove the <em>first</em> occurrence of the
    163     * given object, not <em>all</em> occurrences.
    164     * </p>
    165     *
    166     * @param object  The object to remove.
    167     * @return {@code true} if this call changed the collection.
    168     */
    169    @Override
    170    boolean remove(Object object);
    171
    172    /**
    173     * Removes {@code nCopies} copies of the specified object from the Bag.
    174     * <p>
    175     * If the number of copies to remove is greater than the actual number of
    176     * copies in the Bag, no error is thrown.
    177     * </p>
    178     *
    179     * @param object  The object to remove.
    180     * @param nCopies  The number of copies to remove.
    181     * @return {@code true} if this call changed the collection.
    182     */
    183    boolean remove(Object object, int nCopies);
    184
    185    /**
    186     * <em>(Violation)</em>
    187     * Remove all elements represented in the given collection,
    188     * respecting cardinality. That is, if the given collection
    189     * {@code coll} contains {@code n} copies of a given object,
    190     * the bag will have {@code n} fewer copies, assuming the bag
    191     * had at least {@code n} copies to begin with.
    192     *
    193     * <p>
    194     * The {@link Collection#removeAll(Collection)} method specifies
    195     * that cardinality should <em>not</em> be respected; this method should
    196     * remove <em>all</em> occurrences of every object contained in the
    197     * given collection.
    198     * </p>
    199     *
    200     * @param coll  The collection to remove.
    201     * @return {@code true} if this call changed the collection.
    202     */
    203    @Override
    204    boolean removeAll(Collection<?> coll);
    205
    206    /**
    207     * <em>(Violation)</em>
    208     * Remove any members of the bag that are not in the given
    209     * collection, respecting cardinality. That is, if the given
    210     * collection {@code coll} contains {@code n} copies of a
    211     * given object and the bag has {@code m > n} copies, then
    212     * delete {@code m - n} copies from the bag. In addition, if
    213     * {@code e} is an object in the bag but
    214     * {@code !coll.contains(e)}, then remove {@code e} and any
    215     * of its copies.
    216     *
    217     * <p>
    218     * The {@link Collection#retainAll(Collection)} method specifies
    219     * that cardinality should <em>not</em> be respected; this method should
    220     * keep <em>all</em> occurrences of every object contained in the
    221     * given collection.
    222     * </p>
    223     *
    224     * @param coll  The collection to retain.
    225     * @return {@code true} if this call changed the collection.
    226     */
    227    @Override
    228    boolean retainAll(Collection<?> coll);
    229
    230    /**
    231     * Returns the total number of items in the bag across all types.
    232     *
    233     * @return The total size of the Bag.
    234     */
    235    @Override
    236    int size();
    237
    238    /**
    239     * Returns a {@link Set} of unique elements in the Bag.
    240     * <p>
    241     * Uniqueness constraints are the same as those in {@link Set}.
    242     * </p>
    243     *
    244     * @return The Set of unique Bag elements.
    245     */
    246    Set<E> uniqueSet();
    247
    248    // The following is not part of the formal Bag interface, however where possible
    249    // Bag implementations should follow these comments.
    250//    /**
    251//     * Compares this Bag to another.
    252//     * This Bag equals another Bag if it contains the same number of occurrences of
    253//     * the same elements.
    254//     * This equals definition is compatible with the Set interface.
    255//     *
    256//     * @param obj  The Bag to compare to
    257//     * @return true if equal
    258//     */
    259//    boolean equals(Object obj);
    260//
    261//    /**
    262//     * Gets a hash code for the Bag compatible with the definition of equals.
    263//     * The hash code is defined as the sum total of a hash code for each element.
    264//     * The per element hash code is defined as
    265//     * {@code (e==null ? 0 : e.hashCode()) ^ noOccurrences)}.
    266//     * This hash code definition is compatible with the Set interface.
    267//     *
    268//     * @return The hash code of the Bag
    269//     */
    270//    int hashCode();
    271
    272}