    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.Map;
    021import java.util.Map.Entry;
    022import java.util.Set;
    023
    024/**
    025 * Defines a map that holds a collection of values against each key.
    026 * <p>
    027 * A {@code MultiValuedMap} is a Map with slightly different semantics:
    028 * <ul>
    029 *   <li>Putting a value into the map will add the value to a {@link Collection} at that key.</li>
    030 *   <li>Getting a value will return a {@link Collection}, holding all the values put to that key.</li>
    031 * </ul>
    032 * <p>
    033 * For example:
    034 * <pre>
    035 * MultiValuedMap&lt;K, String&gt; map = new MultiValuedHashMap&lt;K, String&gt;();
    036 * map.put(key, &quot;A&quot;);
    037 * map.put(key, &quot;B&quot;);
    038 * map.put(key, &quot;C&quot;);
    039 * Collection&lt;String&gt; coll = map.get(key);
    040 * </pre>
    041 * <p>
    042 * <code>coll</code> will be a collection containing "A", "B", "C".
    043 * <p>
    044 *
    045 * @param <K> the type of the keys in this map
    046 * @param <V> the type of the values in this map
    047 * @since 4.1
    048 */
    049public interface MultiValuedMap<K, V> {
    050    // Query operations
    051
    052    /**
    053     * Gets the total size of the map.
    054     * <p>
    055     * Implementations would return the total size of the map which is the count
    056     * of the values from all keys.
    057     *
    058     * @return the total size of the map
    059     */
    060    int size();
    061
    062    /**
    063     * Returns {@code true} if this map contains no key-value mappings.
    064     *
    065     * @return {@code true} if this map contains no key-value mappings
    066     */
    067    boolean isEmpty();
    068
    069    /**
    070     * Returns {@code true} if this map contains a mapping for the specified
    071     * key. More formally, returns {@code true} if and only if this map contains
    072     * a mapping for a key {@code k} such that {@code (key==null ? k==null : key.equals(k))}.
    073     * (There can be at most one such mapping.)
    074     *
    075     * @param key  key whose presence in this map is to be tested
    076     * @return true if this map contains a mapping for the specified key
    077     * @throws NullPointerException if the specified key is null and this map
    078     *   does not permit null keys (optional)
    079     */
    080    boolean containsKey(Object key);
    081
    082    /**
    083     * Checks whether the map contains at least one mapping for the specified value.
    084     *
    085     * @param value  the value to search for
    086     * @return true if the map contains the value
    087     * @throws NullPointerException if the value is null and null values are not supported
    088     *   by the used collection types (optional)
    089     */
    090    boolean containsValue(Object value);
    091
    092    /**
    093     * Checks whether the map contains a mapping for the specified key and value.
    094     *
    095     * @param key  the key to search for
    096     * @param value  the value to search for
    097     * @return true if the map contains the value
    098     */
    099    boolean containsMapping(Object key, Object value);
    100
    101    /**
    102     * Returns a view collection of the values associated with the specified key.
    103     * <p>
    104     * This method will return an <b>empty</b> collection if {@link #containsKey(Object)}
    105     * returns {@code false}. Changes to the returned collection will update the underlying
    106     * {@code MultiValuedMap} and vice-versa.
    107     *
    108     * @param key  the key to retrieve
    109     * @return the {@code Collection} of values, implementations should
    110     *   return an empty collection for no mapping
    111     * @throws NullPointerException if the key is null and null keys are invalid (optional)
    112     */
    113    Collection<V> get(K key);
    114
    115    // Modification operations
    116
    117    /**
    118     * Adds a key-value mapping to this multi-valued map.
    119     * <p>
    120     * Unlike a normal {@code Map} the previous value is not replaced.
    121     * Instead the new value is added to the collection stored against the key.
    122     * Depending on the collection type used, duplicate key-value mappings may
    123     * be allowed.
    124     * <p>
    125     * The method will return {@code true} if the size of the multi-valued map
    126     * has been increased because of this operation.
    127     *
    128     * @param key  the key to store against
    129     * @param value  the value to add to the collection at the key
    130     * @return true if the map changed as a result of this put operation, or false
    131     *   if the map already contained the key-value mapping and the collection
    132     *   type does not allow duplicate values, e.g. when using a Set
    133     * @throws UnsupportedOperationException if the put operation is not supported by
    134     *   this multi-valued map, e.g. if it is unmodifiable
    135     * @throws NullPointerException if the key or value is null and null is invalid (optional)
    136     * @throws IllegalArgumentException if some aspect of the specified key or value prevents
    137     *   it from being stored in this multi-valued map
    138     */
    139    boolean put(K key, V value);
    140
    141    /**
    142     * Adds a mapping to the specified key for all values contained in the given Iterable.
    143     *
    144     * @param key  the key to store against
    145     * @param values  the values to add to the collection at the key, may not be null
    146     * @return true if the map changed as a result of this operation
    147     * @throws NullPointerException if the specified iterable is null, or if this map
    148     *   does not permit null keys or values, and the specified key or values contain
    149     *   null (optional)
    150     */
    151    boolean putAll(K key, Iterable<? extends V> values);
    152
    153    /**
    154     * Copies all mappings from the specified map to this multi-valued map
    155     * (optional operation).
    156     * <p>
    157     * The effect of this call is equivalent to that of calling
    158     * {@link #put(Object,Object) put(k, v)} on this map once for each mapping
    159     * from key {@code k} to value {@code v} in the specified map.
    160     * <p>
    161     * The behavior of this operation is undefined if the specified map is modified
    162     * while the operation is in progress.
    163     *
    164     * @param map  mappings to be stored in this map, may not be null
    165     * @return true if the map changed as a result of this operation
    166     * @throws UnsupportedOperationException if the {@code putAll} operation is
    167     *   not supported by this map
    168     * @throws NullPointerException if the specified map is null, or if this map
    169     *   does not permit null keys or values, and the specified map
    170     *   contains null keys or values (optional)
    171     * @throws IllegalArgumentException if some property of a key or value in
    172     *   the specified map prevents it from being stored in this map
    173     */
    174    boolean putAll(Map<? extends K, ? extends V> map);
    175
    176    /**
    177     * Copies all mappings from the specified map to this multi-valued map
    178     * (optional operation).
    179     * <p>
    180     * The effect of this call is equivalent to that of calling
    181     * {@link #put(Object,Object) put(k, v)} on this map once for each
    182     * mapping from key {@code k} to value {@code v} in the specified map.
    183     * <p>
    184     * The behavior of this operation is undefined if the specified map is modified
    185     * while the operation is in progress.
    186     *
    187     * @param map  mappings to be stored in this map, may not be null
    188     * @return true if the map changed as a result of this operation
    189     * @throws UnsupportedOperationException if the {@code putAll} operation is
    190     *   not supported by this map
    191     * @throws NullPointerException if the specified map is null, or if this map
    192     *   does not permit null keys or values, and the specified map
    193     *   contains null keys or values (optional)
    194     * @throws IllegalArgumentException if some property of a key or value in
    195     *   the specified map prevents it from being stored in this map
    196     */
    197    boolean putAll(MultiValuedMap<? extends K, ? extends V> map);
    198
    199    /**
    200     * Removes all values associated with the specified key.
    201     * <p>
    202     * The returned collection <i>may</i> be modifiable, but updates will not be propagated
    203     * to this multi-valued map. In case no mapping was stored for the specified
    204     * key, an empty, unmodifiable collection will be returned.
    205     *
    206     * @param key  the key to remove values from
    207     * @return the values that were removed
    208     * @throws UnsupportedOperationException if the map is unmodifiable
    209     * @throws NullPointerException if the key is null and null keys are invalid (optional)
    210     */
    211    Collection<V> remove(Object key);
    212
    213    /**
    214     * Removes a key-value mapping from the map.
    215     * <p>
    216     * The item is removed from the collection mapped to the specified key.
    217     * Other values attached to that key are unaffected.
    218     * <p>
    219     * If the last value for a key is removed, implementations typically return
    220     * an empty collection from a subsequent <code>get(Object)</code>.
    221     *
    222     * @param key  the key to remove from
    223     * @param item  the item to remove
    224     * @return true if the mapping was removed, false otherwise
    225     * @throws UnsupportedOperationException if the map is unmodifiable
    226     * @throws NullPointerException if the key or value is null and null is invalid (optional)
    227     */
    228    boolean removeMapping(Object key, Object item);
    229
    230    /**
    231     * Removes all of the mappings from this map (optional operation).
    232     * <p>
    233     * The map will be empty after this call returns.
    234     *
    235     * @throws UnsupportedOperationException if the map is unmodifiable
    236     */
    237    void clear();
    238
    239    // Views
    240
    241    /**
    242     * Returns a {@link Collection} view of the mappings contained in this multi-valued map.
    243     * <p>
    244     * The collection is backed by the map, so changes to the map are reflected
    245     * in the collection, and vice-versa.
    246     *
    247     * @return a set view of the mappings contained in this map
    248     */
    249    Collection<Entry<K, V>> entries();
    250
    251    /**
    252     * Returns a {@link MultiSet} view of the keys contained in this multi-valued map.
    253     * <p>
    254     * The {@link MultiSet#getCount(Object)} method of the returned multiset will give
    255     * the same result a calling {@code get(Object).size()} for the same key.
    256     * <p>
    257     * This multiset is backed by the map, so any changes in the map are reflected in
    258     * the multiset.
    259     *
    260     * @return a multiset view of the keys contained in this map
    261     */
    262    MultiSet<K> keys();
    263
    264    /**
    265     * Returns a {@link Set} view of the keys contained in this multi-valued map.
    266     * <p>
    267     * The set is backed by the map, so changes to the map are reflected
    268     * in the set, and vice-versa.
    269     * <p>
    270     * If the map is modified while an iteration over the set is in
    271     * progress (except through the iterator's own {@code remove} operation),
    272     * the result of the iteration is undefined. The set supports element
    273     * removal, which removes the corresponding mapping from the map, via the
    274     * {@code Iterator.remove}, {@code Set.remove}, {@code removeAll},
    275     * {@code retainAll}, and {@code clear} operations. It does not support
    276     * the {@code add} or {@code addAll} operations.
    277     *
    278     * @return a set view of the keys contained in this map
    279     */
    280    Set<K> keySet();
    281
    282    /**
    283     * Gets a {@link Collection} view of all values contained in this multi-valued map.
    284     * <p>
    285     * Implementations typically return a collection containing the combination
    286     * of values from all keys.
    287     *
    288     * @return a collection view of the values contained in this multi-valued map
    289     */
    290    Collection<V> values();
    291
    292    /**
    293     * Returns a view of this multi-valued map as a {@code Map} from each distinct
    294     * key to the non-empty collection of that key's associated values.
    295     * <p>
    296     * Note that {@code this.asMap().get(k)} is equivalent to {@code this.get(k)}
    297     * only when {@code k} is a key contained in the multi-valued map; otherwise it
    298     * returns {@code null} as opposed to an empty collection.
    299     * <p>
    300     * Changes to the returned map or the collections that serve as its values
    301     * will update the underlying multi-valued map, and vice versa. The map does
    302     * not support {@code put} or {@code putAll}, nor do its entries support
    303     * {@link java.util.Map.Entry#setValue(Object) setValue}.
    304     *
    305     * @return a map view of the mappings in this multi-valued map
    306     */
    307    Map<K, Collection<V>> asMap();
    308
    309    // Iterators
    310
    311    /**
    312     * Obtains a <code>MapIterator</code> over this multi-valued map.
    313     * <p>
    314     * A map iterator is an efficient way of iterating over maps. There is no
    315     * need to access the entries collection or use {@code Map.Entry} objects.
    316     *
    317     * @return a map iterator
    318     */
    319    MapIterator<K, V> mapIterator();
    320
    321}