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 <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 }