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}