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 * https://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 */ 017 018package org.apache.commons.collections4; 019 020import java.util.Collection; 021import java.util.Map; 022import java.util.Map.Entry; 023import java.util.Set; 024 025/** 026 * Defines a map that holds a collection of values against each key. 027 * <p> 028 * A {@code MultiValuedMap} is a Map with slightly different semantics: 029 * </p> 030 * <ul> 031 * <li>Putting a value into the map will add the value to a {@link Collection} at that key.</li> 032 * <li>Getting a value will return a {@link Collection}, holding all the values put to that key.</li> 033 * </ul> 034 * <p> 035 * For example: 036 * </p> 037 * 038 * <pre>{@code 039 * MultiValuedMap<Integer, String> map = new ArrayListValuedHashMap<>(); 040 * map.put(1, "A"); 041 * map.put(1, "B"); 042 * map.put(1, "C"); 043 * Collection<String> coll = map.get(1); 044 * }</pre> 045 * <p> 046 * {@code coll} will be a collection containing "A", "B", "C". 047 * </p> 048 * 049 * @param <K> The type of the keys in this map 050 * @param <V> The type of the values in this map 051 * @since 4.1 052 */ 053public interface MultiValuedMap<K, V> { 054 // Query operations 055 056 /** 057 * 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. 058 * <p> 059 * 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 060 * returns {@code null} as opposed to an empty collection. 061 * </p> 062 * <p> 063 * 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 064 * support {@code put} or {@code putAll}, nor do its entries support {@link java.util.Map.Entry#setValue(Object) setValue}. 065 * </p> 066 * 067 * @return A map view of the mappings in this multivalued map. 068 */ 069 Map<K, Collection<V>> asMap(); 070 071 /** 072 * Removes all of the mappings from this map (optional operation). 073 * <p> 074 * The map will be empty after this call returns. 075 * </p> 076 * 077 * @throws UnsupportedOperationException if the map is unmodifiable. 078 */ 079 void clear(); 080 081 /** 082 * 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 083 * for a key {@code k} such that {@code (key==null ? k==null : key.equals(k))}. (There can be at most one such mapping.) 084 * 085 * @param key key whose presence in this map is to be tested. 086 * @return true if this map contains a mapping for the specified key. 087 * @throws NullPointerException if the specified key is null and this map does not permit null keys (optional). 088 */ 089 boolean containsKey(Object key); 090 091 /** 092 * Checks whether the map contains a mapping for the specified key and value. 093 * 094 * @param key The key to search for. 095 * @param value The value to search for. 096 * @return true if the map contains the value. 097 */ 098 boolean containsMapping(Object key, Object value); 099 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}