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    *      https://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  
18  package org.apache.commons.collections4;
19  
20  import java.util.Collection;
21  import java.util.Map;
22  import java.util.Map.Entry;
23  import java.util.Set;
24  
25  /**
26   * Defines a map that holds a collection of values against each key.
27   * <p>
28   * A {@code MultiValuedMap} is a Map with slightly different semantics:
29   * </p>
30   * <ul>
31   * <li>Putting a value into the map will add the value to a {@link Collection} at that key.</li>
32   * <li>Getting a value will return a {@link Collection}, holding all the values put to that key.</li>
33   * </ul>
34   * <p>
35   * For example:
36   * </p>
37   *
38   * <pre>{@code
39   * MultiValuedMap<Integer, String> map = new ArrayListValuedHashMap<>();
40   * map.put(1, "A");
41   * map.put(1, "B");
42   * map.put(1, "C");
43   * Collection<String> coll = map.get(1);
44   * }</pre>
45   * <p>
46   * {@code coll} will be a collection containing "A", "B", "C".
47   * </p>
48   *
49   * @param <K> The type of the keys in this map
50   * @param <V> The type of the values in this map
51   * @since 4.1
52   */
53  public interface MultiValuedMap<K, V> {
54      // Query operations
55  
56      /**
57       * Returns a view of this multivalued map as a {@code Map} from each distinct key to the non-empty collection of that key's associated values.
58       * <p>
59       * Note that {@code this.asMap().get(k)} is equivalent to {@code this.get(k)} 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 will update the underlying multivalued map, and vice versa. The map does not
64       * support {@code put} or {@code putAll}, nor do its entries support {@link java.util.Map.Entry#setValue(Object) setValue}.
65       * </p>
66       *
67       * @return A map view of the mappings in this multivalued map.
68       */
69      Map<K, Collection<V>> asMap();
70  
71      /**
72       * Removes all of the mappings from this map (optional operation).
73       * <p>
74       * The map will be empty after this call returns.
75       * </p>
76       *
77       * @throws UnsupportedOperationException if the map is unmodifiable.
78       */
79      void clear();
80  
81      /**
82       * Returns {@code true} if this map contains a mapping for the specified key. More formally, returns {@code true} if and only if this map contains a mapping
83       * for a key {@code k} such that {@code (key==null ? k==null : key.equals(k))}. (There can be at most one such mapping.)
84       *
85       * @param key key whose presence in this map is to be tested.
86       * @return true if this map contains a mapping for the specified key.
87       * @throws NullPointerException if the specified key is null and this map does not permit null keys (optional).
88       */
89      boolean containsKey(Object key);
90  
91      /**
92       * Checks whether the map contains a mapping for the specified key and value.
93       *
94       * @param key   The key to search for.
95       * @param value The value to search for.
96       * @return true if the map contains the value.
97       */
98      boolean containsMapping(Object key, Object value);
99  
100     /**
101      * Checks whether the map contains at least one mapping for the specified value.
102      *
103      * @param value The value to search for.
104      * @return true if the map contains the value.
105      * @throws NullPointerException if the value is null and null values are not supported by the used collection types (optional).
106      */
107     boolean containsValue(Object value);
108 
109     /**
110      * Returns a {@link Collection} view of the mappings contained in this multivalued map.
111      * <p>
112      * The collection is backed by the map, so changes to the map are reflected in the collection, and vice-versa.
113      * </p>
114      *
115      * @return A set view of the mappings contained in this map.
116      */
117     Collection<Entry<K, V>> entries();
118     // Modification operations
119 
120     /**
121      * Gets a view collection of the values associated with the specified key.
122      * <p>
123      * This method will return an <strong>empty</strong> collection if {@link #containsKey(Object)} returns {@code false}. Changes to the returned collection
124      * will update the underlying {@code MultiValuedMap} and vice-versa.
125      * </p>
126      *
127      * @param key The key to retrieve.
128      * @return The {@code Collection} of values, implementations should return an empty collection for no mapping.
129      * @throws NullPointerException if the key is null and null keys are invalid (optional).
130      */
131     Collection<V> get(K key);
132 
133     /**
134      * Always throws {@link UnsupportedOperationException}.
135      *
136      * @return Always throws {@link UnsupportedOperationException}.
137      * @throws UnsupportedOperationException Always thrown.
138      * @since 4.6.0
139      */
140     default MultiValuedMap<V, K> inverted() {
141         throw new UnsupportedOperationException(getClass() + ".inverted()");
142     }
143 
144     /**
145      * Returns {@code true} if this map contains no key-value mappings.
146      *
147      * @return {@code true} if this map contains no key-value mappings.
148      */
149     boolean isEmpty();
150 
151     /**
152      * Returns a {@link MultiSet} view of the keys contained in this multivalued map.
153      * <p>
154      * The {@link MultiSet#getCount(Object)} method of the returned multiset will give 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 the multiset.
158      * </p>
159      *
160      * @return A multiset view of the keys contained in this map.
161      */
162     MultiSet<K> keys();
163 
164     /**
165      * Returns a {@link Set} view of the keys contained in this multivalued map.
166      * <p>
167      * The set is backed by the map, so changes to the map are reflected in the set, and vice-versa.
168      * </p>
169      * <p>
170      * If the map is modified while an iteration over the set is in progress (except through the iterator's own {@code remove} operation), the result of the
171      * iteration is undefined. The set supports element removal, which removes the corresponding mapping from the map, via the {@code Iterator.remove},
172      * {@code Set.remove}, {@code removeAll}, {@code retainAll}, and {@code clear} operations. It does not support the {@code add} or {@code addAll} operations.
173      * </p>
174      *
175      * @return A set view of the keys contained in this map.
176      */
177     Set<K> keySet();
178 
179     /**
180      * Obtains a {@code MapIterator} over this multivalued map.
181      * <p>
182      * A map iterator is an efficient way of iterating over maps. There is no need to access the entries collection or use {@code Map.Entry} objects.
183      * </p>
184      *
185      * @return A map iterator.
186      */
187     MapIterator<K, V> mapIterator();
188 
189     /**
190      * Adds a key-value mapping to this multivalued map.
191      * <p>
192      * Unlike a normal {@code Map} the previous value is not replaced. Instead, the new value is added to the collection stored against the key. Depending on
193      * the collection type used, duplicate key-value mappings may be allowed.
194      * </p>
195      * <p>
196      * The method will return {@code true} if the size of the multivalued map has been increased because of this operation.
197      * </p>
198      *
199      * @param key   The key to store against.
200      * @param value The value to add to the collection at the key.
201      * @return true if the map changed as a result of this put operation, or false if the map already contained the key-value mapping and the collection type
202      *         does not allow duplicate values, for example when using a Set.
203      * @throws UnsupportedOperationException if the put operation is not supported by this multivalued map, for example if it is unmodifiable.
204      * @throws NullPointerException          if the key or value is null and null is invalid (optional).
205      * @throws IllegalArgumentException      if some aspect of the specified key or value prevents it from being stored in this multivalued map.
206      */
207     boolean put(K key, V value);
208 
209     /**
210      * Adds a mapping to the specified key for all values contained in the given Iterable.
211      *
212      * @param key    The key to store against.
213      * @param values The values to add to the collection at the key, may not be null.
214      * @return true if the map changed as a result of this operation.
215      * @throws NullPointerException if the specified iterable is null, or if this map does not permit null keys or values, and the specified key or values
216      *                              contain null (optional).
217      */
218     boolean putAll(K key, Iterable<? extends V> values);
219 
220     /**
221      * Copies all mappings from the specified map to this multivalued map (optional operation).
222      * <p>
223      * The effect of this call is equivalent to that of calling {@link #put(Object,Object) put(k, v)} on this map once for each mapping from key {@code k} to
224      * value {@code v} in the specified map.
225      * </p>
226      * <p>
227      * The behavior of this operation is undefined if the specified map is modified while the operation is in progress.
228      * </p>
229      *
230      * @param map mappings to be stored in this map, may not be null.
231      * @return true if the map changed as a result of this operation.
232      * @throws UnsupportedOperationException if the {@code putAll} operation is not supported by this map.
233      * @throws NullPointerException          if the specified map is null, or if this map does not permit null keys or values, and the specified map contains
234      *                                       null keys or values (optional).
235      * @throws IllegalArgumentException      if some property of a key or value in the specified map prevents it from being stored in this map.
236      */
237     boolean putAll(Map<? extends K, ? extends V> map);
238 
239     /**
240      * Copies all mappings from the specified map to this multivalued map (optional operation).
241      * <p>
242      * The effect of this call is equivalent to that of calling {@link #put(Object,Object) put(k, v)} on this map once for each mapping from key {@code k} to
243      * value {@code v} in the specified map.
244      * </p>
245      * <p>
246      * The behavior of this operation is undefined if the specified map is modified 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 not supported by this map.
252      * @throws NullPointerException          if the specified map is null, or if this map does not permit null keys or values, and the specified map contains
253      *                                       null keys or values (optional).
254      * @throws IllegalArgumentException      if some property of a key or value in the specified map prevents it from being stored in this map.
255      */
256     boolean putAll(MultiValuedMap<? extends K, ? extends V> map);
257 
258     /**
259      * Removes all values associated with the specified key.
260      * <p>
261      * The returned collection <em>may</em> be modifiable, but updates will not be propagated to this multivalued map. In case no mapping was stored for the
262      * specified key, an empty, unmodifiable collection will be returned.
263      * </p>
264      *
265      * @param key The key to remove values from.
266      * @return The values that were removed.
267      * @throws UnsupportedOperationException if the map is unmodifiable.
268      * @throws NullPointerException          if the key is null and null keys are invalid (optional).
269      */
270     Collection<V> remove(Object key);
271 
272     /**
273      * Removes a key-value mapping from the map.
274      * <p>
275      * The item is removed from the collection mapped to the specified key. Other values attached to that key are unaffected.
276      * </p>
277      * <p>
278      * If the last value for a key is removed, implementations typically return an empty collection from a subsequent {@code get(Object)}.
279      * </p>
280      *
281      * @param key  The key to remove from.
282      * @param item The item to remove.
283      * @return true if the mapping was removed, false otherwise.
284      * @throws UnsupportedOperationException if the map is unmodifiable.
285      * @throws NullPointerException          if the key or value is null and null is invalid (optional).
286      */
287     boolean removeMapping(Object key, Object item);
288 
289     /**
290      * Gets the total size of the map.
291      * <p>
292      * Implementations would return the total size of the map which is the count of the values from all keys.
293      * </p>
294      *
295      * @return The total size of the map.
296      */
297     int size();
298 
299     /**
300      * Gets a {@link Collection} view of all values contained in this multivalued map.
301      * <p>
302      * Implementations typically return a collection containing the combination of values from all keys.
303      * </p>
304      *
305      * @return A collection view of the values contained in this multivalued map.
306      */
307     Collection<V> values();
308 }