View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4;
18  
19  import java.util.Collection;
20  import java.util.Map;
21  import java.util.Map.Entry;
22  import java.util.Set;
23  
24  /**
25   * Defines a map that holds a collection of values against each key.
26   * <p>
27   * A {@code MultiValuedMap} is a Map with slightly different semantics:
28   * </p>
29   * <ul>
30   *   <li>Putting a value into the map will add the value to a {@link Collection} at that key.</li>
31   *   <li>Getting a value will return a {@link Collection}, holding all the values put to that key.</li>
32   * </ul>
33   * <p>
34   * For example:
35   * </p>
36   * <pre>{@code
37   * MultiValuedMap<Integer, String> map = new ArrayListValuedHashMap<>();
38   * map.put(1, "A");
39   * map.put(1, "B");
40   * map.put(1, "C");
41   * Collection<String> coll = map.get(1);
42   * }</pre>
43   * <p>
44   * {@code coll} will be a collection containing "A", "B", "C".
45   * </p>
46   *
47   * @param <K> the type of the keys in this map
48   * @param <V> the type of the values in this map
49   * @since 4.1
50   */
51  public interface MultiValuedMap<K, V> {
52      // Query operations
53  
54      /**
55       * Returns a view of this multivalued map as a {@code Map} from each distinct
56       * key to the non-empty collection of that key's associated values.
57       * <p>
58       * Note that {@code this.asMap().get(k)} is equivalent to {@code this.get(k)}
59       * only when {@code k} is a key contained in the multivalued map; otherwise it
60       * returns {@code null} as opposed to an empty collection.
61       * </p>
62       * <p>
63       * Changes to the returned map or the collections that serve as its values
64       * will update the underlying multivalued map, and vice versa. The map does
65       * not support {@code put} or {@code putAll}, nor do its entries support
66       * {@link java.util.Map.Entry#setValue(Object) setValue}.
67       * </p>
68       *
69       * @return a map view of the mappings in this multivalued map
70       */
71      Map<K, Collection<V>> asMap();
72  
73      /**
74       * Removes all of the mappings from this map (optional operation).
75       * <p>
76       * The map will be empty after this call returns.
77       * </p>
78       *
79       * @throws UnsupportedOperationException if the map is unmodifiable
80       */
81      void clear();
82  
83      /**
84       * Returns {@code true} if this map contains a mapping for the specified
85       * key. More formally, returns {@code true} if and only if this map contains
86       * a mapping for a key {@code k} such that {@code (key==null ? k==null : key.equals(k))}.
87       * (There can be at most one such mapping.)
88       *
89       * @param key  key whose presence in this map is to be tested
90       * @return true if this map contains a mapping for the specified key
91       * @throws NullPointerException if the specified key is null and this map
92       *   does not permit null keys (optional)
93       */
94      boolean containsKey(Object key);
95  
96      /**
97       * Checks whether the map contains a mapping for the specified key and value.
98       *
99       * @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 <b>empty</b> 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     // Views
235 
236     /**
237      * Copies all mappings from the specified map to this multivalued map
238      * (optional operation).
239      * <p>
240      * The effect of this call is equivalent to that of calling
241      * {@link #put(Object,Object) put(k, v)} on this map once for each mapping
242      * from key {@code k} to value {@code v} in the specified map.
243      * </p>
244      * <p>
245      * The behavior of this operation is undefined if the specified map is modified
246      * while the operation is in progress.
247      * </p>
248      *
249      * @param map  mappings to be stored in this map, may not be null
250      * @return true if the map changed as a result of this operation
251      * @throws UnsupportedOperationException if the {@code putAll} operation is
252      *   not supported by this map
253      * @throws NullPointerException if the specified map is null, or if this map
254      *   does not permit null keys or values, and the specified map
255      *   contains null keys or values (optional)
256      * @throws IllegalArgumentException if some property of a key or value in
257      *   the specified map prevents it from being stored in this map
258      */
259     boolean putAll(Map<? extends K, ? extends V> map);
260 
261     /**
262      * Copies all mappings from the specified map to this multivalued map
263      * (optional operation).
264      * <p>
265      * The effect of this call is equivalent to that of calling
266      * {@link #put(Object,Object) put(k, v)} on this map once for each
267      * mapping from key {@code k} to value {@code v} in the specified map.
268      * </p>
269      * <p>
270      * The behavior of this operation is undefined if the specified map is modified
271      * while the operation is in progress.
272      * </p>
273      *
274      * @param map  mappings to be stored in this map, may not be null
275      * @return true if the map changed as a result of this operation
276      * @throws UnsupportedOperationException if the {@code putAll} operation is
277      *   not supported by this map
278      * @throws NullPointerException if the specified map is null, or if this map
279      *   does not permit null keys or values, and the specified map
280      *   contains null keys or values (optional)
281      * @throws IllegalArgumentException if some property of a key or value in
282      *   the specified map prevents it from being stored in this map
283      */
284     boolean putAll(MultiValuedMap<? extends K, ? extends V> map);
285 
286     /**
287      * Removes all values associated with the specified key.
288      * <p>
289      * The returned collection <i>may</i> be modifiable, but updates will not be propagated
290      * to this multivalued map. In case no mapping was stored for the specified
291      * key, an empty, unmodifiable collection will be returned.
292      * </p>
293      *
294      * @param key  the key to remove values from
295      * @return the values that were removed
296      * @throws UnsupportedOperationException if the map is unmodifiable
297      * @throws NullPointerException if the key is null and null keys are invalid (optional)
298      */
299     Collection<V> remove(Object key);
300 
301     /**
302      * Removes a key-value mapping from the map.
303      * <p>
304      * The item is removed from the collection mapped to the specified key.
305      * Other values attached to that key are unaffected.
306      * </p>
307      * <p>
308      * If the last value for a key is removed, implementations typically return
309      * an empty collection from a subsequent {@code get(Object)}.
310      * </p>
311      *
312      * @param key  the key to remove from
313      * @param item  the item to remove
314      * @return true if the mapping was removed, false otherwise
315      * @throws UnsupportedOperationException if the map is unmodifiable
316      * @throws NullPointerException if the key or value is null and null is invalid (optional)
317      */
318     boolean removeMapping(Object key, Object item);
319 
320     /**
321      * Gets the total size of the map.
322      * <p>
323      * Implementations would return the total size of the map which is the count
324      * of the values from all keys.
325      * </p>
326      *
327      * @return the total size of the map
328      */
329     int size();
330 
331     /**
332      * Gets a {@link Collection} view of all values contained in this multivalued map.
333      * <p>
334      * Implementations typically return a collection containing the combination
335      * of values from all keys.
336      * </p>
337      *
338      * @return a collection view of the values contained in this multivalued map
339      */
340     Collection<V> values();
341 
342 }