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