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 }