    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 MultiSet 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 *
    032 * @param <E> the type held in the multiset
    033 * @since 4.1
    034 */
    035public interface MultiSet<E> extends Collection<E> {
    036
    037    /**
    038     * Returns the number of occurrences of the given object currently
    039     * in the MultiSet. If the object does not exist in the multiset,
    040     * return 0.
    041     *
    042     * @param object  the object to search for
    043     * @return the number of occurrences of the object, zero if not found
    044     */
    045    int getCount(Object object);
    046
    047    /**
    048     * Sets the number of occurrences of the specified object in the MultiSet
    049     * to the given count.
    050     * <p>
    051     * If the provided count is zero, the object will be removed from the
    052     * {@link #uniqueSet()}.
    053     *
    054     * @param object  the object to update
    055     * @param count  the number of occurrences of the object
    056     * @return the number of occurrences of the object before this operation, zero
    057     *   if the object was not contained in the multiset
    058     * @throws IllegalArgumentException if count is negative
    059     */
    060    int setCount(E object, int count);
    061
    062    /**
    063     * Adds one copy of the specified object to the MultiSet.
    064     * <p>
    065     * If the object is already in the {@link #uniqueSet()} then increment its
    066     * count as reported by {@link #getCount(Object)}. Otherwise add it to the
    067     * {@link #uniqueSet()} and report its count as 1.
    068     *
    069     * @param object  the object to add
    070     * @return <code>true</code> always, as the size of the MultiSet is increased
    071     *   in any case
    072     */
    073    @Override
    074    boolean add(E object);
    075
    076    /**
    077     * Adds a number of occurrences of the specified object to the MultiSet.
    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>occurrences</code>.
    082     *
    083     * @param object  the object to add
    084     * @param occurrences  the number of occurrences to add, may be zero,
    085     *   in which case no change is made to the multiset
    086     * @return the number of occurrences of the object in the multiset before
    087     *   this operation; possibly zero
    088     * @throws IllegalArgumentException if occurrences is negative
    089     */
    090    int add(E object, int occurrences);
    091
    092    /**
    093     * Removes one occurrence of the given object from the MultiSet.
    094     * <p>
    095     * If the number of occurrences after this operations is reduced
    096     * to zero, the object will be removed from the {@link #uniqueSet()}.
    097     *
    098     * @param object  the object to remove
    099     * @return <code>true</code> if this call changed the collection
    100     */
    101    @Override
    102    boolean remove(Object object);
    103
    104    /**
    105     * Removes a number of occurrences of the specified object from the MultiSet.
    106     * <p>
    107     * If the number of occurrences to remove is greater than the actual number of
    108     * occurrences in the multiset, the object will be removed from the multiset.
    109     *
    110     * @param object  the object to remove
    111     * @param occurrences  the number of occurrences to remove, may be zero,
    112     *   in which case no change is made to the multiset
    113     * @return the number of occurrences of the object in the multiset
    114     *   before the operation; possibly zero
    115     * @throws IllegalArgumentException if occurrences is negative
    116     */
    117    int remove(Object object, int occurrences);
    118
    119    /**
    120     * Returns a {@link Set} of unique elements in the MultiSet.
    121     * <p>
    122     * Uniqueness constraints are the same as those in {@link java.util.Set}.
    123     * <p>
    124     * The returned set is backed by this multiset, so any change to either
    125     * is immediately reflected in the other. Only removal operations are
    126     * supported, in which case all occurrences of the element are removed
    127     * from the backing multiset.
    128     *
    129     * @return the Set of unique MultiSet elements
    130     */
    131    Set<E> uniqueSet();
    132
    133    /**
    134     * Returns a {@link Set} of all entries contained in the MultiSet.
    135     * <p>
    136     * The returned set is backed by this multiset, so any change to either
    137     * is immediately reflected in the other.
    138     *
    139     * @return the Set of MultiSet entries
    140     */
    141    Set<Entry<E>> entrySet();
    142
    143    /**
    144     * Returns an {@link Iterator} over the entire set of members,
    145     * including copies due to cardinality. This iterator is fail-fast
    146     * and will not tolerate concurrent modifications.
    147     *
    148     * @return iterator over all elements in the MultiSet
    149     */
    150    @Override
    151    Iterator<E> iterator();
    152
    153    /**
    154     * Returns the total number of items in the MultiSet.
    155     *
    156     * @return the total size of the multiset
    157     */
    158    @Override
    159    int size();
    160
    161    /**
    162     * Returns <code>true</code> if the MultiSet contains at least one
    163     * occurrence for each element contained in the given collection.
    164     *
    165     * @param coll  the collection to check against
    166     * @return <code>true</code> if the MultiSet contains all the collection
    167     */
    168    @Override
    169    boolean containsAll(Collection<?> coll);
    170
    171    /**
    172     * Remove all occurrences of all elements from this MultiSet represented
    173     * in the given collection.
    174     *
    175     * @param coll  the collection of elements to remove
    176     * @return <code>true</code> if this call changed the multiset
    177     */
    178    @Override
    179    boolean removeAll(Collection<?> coll);
    180
    181    /**
    182     * Remove any elements of this MultiSet that are not contained in the
    183     * given collection.
    184     *
    185     * @param coll  the collection of elements to retain
    186     * @return <code>true</code> if this call changed the multiset
    187     */
    188    @Override
    189    boolean retainAll(Collection<?> coll);
    190
    191    /**
    192     * Compares this MultiSet to another object.
    193     * <p>
    194     * This MultiSet equals another object if it is also a MultiSet
    195     * that contains the same number of occurrences of the same elements.
    196     *
    197     * @param obj  the object to compare to
    198     * @return true if equal
    199     */
    200    @Override
    201    boolean equals(Object obj);
    202
    203    /**
    204     * Gets a hash code for the MultiSet compatible with the definition of equals.
    205     * The hash code is defined as the sum total of a hash code for each element.
    206     * The per element hash code is defined as
    207     * <code>(e==null ? 0 : e.hashCode()) ^ noOccurances)</code>.
    208     *
    209     * @return the hash code of the MultiSet
    210     */
    211    @Override
    212    int hashCode();
    213
    214    /**
    215     * An unmodifiable entry for an element and its occurrence as contained in a MultiSet.
    216     * <p>
    217     * The {@link MultiSet#entrySet()} method returns a view of the multiset whose elements
    218     * implements this interface.
    219     *
    220     * @param <E>  the element type
    221     */
    222    interface Entry<E> {
    223
    224        /**
    225         * Returns the element corresponding to this entry.
    226         *
    227         * @return the element corresponding to this entry
    228         */
    229        E getElement();
    230
    231        /**
    232         * Returns the number of occurrences for the element of this entry.
    233         *
    234         * @return the number of occurrences of the element
    235         */
    236        int getCount();
    237
    238        /**
    239         * Compares the specified object with this entry for equality.
    240         * Returns true if the given object is also a multiset entry
    241         * and the two entries represent the same element with the same
    242         * number of occurrences.
    243         * <p>
    244         * More formally, two entries <code>e1</code> and <code>e2</code> represent
    245         * the same mapping if
    246         * <pre>
    247         *     (e1.getElement()==null ? e2.getElement()==null
    248         *                            : e1.getElement().equals(e2.getElement())) &amp;&amp;
    249         *     (e1.getCount()==e2.getCount())
    250         * </pre>
    251         *
    252         * @param o object to be compared for equality with this multiset entry
    253         * @return true if the specified object is equal to this multiset entry
    254         */
    255        @Override
    256        boolean equals(Object o);
    257
    258        /**
    259         * Returns the hash code value for this multiset entry.
    260         * <p>
    261         * The hash code of a multiset entry <code>e</code> is defined to be:
    262         * <pre>
    263         *      (e==null ? 0 : e.hashCode()) ^ noOccurances)
    264         * </pre>
    265         *
    266         * @return the hash code value for this multiset entry
    267         */
    268        @Override
    269        int hashCode();
    270    }
    271
    272}