1 /* 2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.util; 27 28 import java.util.function.BiConsumer; 29 import java.util.function.BiFunction; 30 import java.util.function.Function; 31 32 /** 33 * An object that maps keys to values. A map cannot contain duplicate keys; 34 * each key can map to at most one value. 35 * 36 * <p>This interface takes the place of the <tt>Dictionary</tt> class, which 37 * was a totally abstract class rather than an interface. 38 * 39 * <p>The <tt>Map</tt> interface provides three <i>collection views</i>, which 40 * allow a map's contents to be viewed as a set of keys, collection of values, 41 * or set of key-value mappings. The <i>order</i> of a map is defined as 42 * the order in which the iterators on the map's collection views return their 43 * elements. Some map implementations, like the <tt>TreeMap</tt> class, make 44 * specific guarantees as to their order; others, like the <tt>HashMap</tt> 45 * class, do not. 46 * 47 * <p>Note: great care must be exercised if mutable objects are used as map 48 * keys. The behavior of a map is not specified if the value of an object is 49 * changed in a manner that affects <tt>equals</tt> comparisons while the 50 * object is a key in the map. A special case of this prohibition is that it 51 * is not permissible for a map to contain itself as a key. While it is 52 * permissible for a map to contain itself as a value, extreme caution is 53 * advised: the <tt>equals</tt> and <tt>hashCode</tt> methods are no longer 54 * well defined on such a map. 55 * 56 * <p>All general-purpose map implementation classes should provide two 57 * "standard" constructors: a void (no arguments) constructor which creates an 58 * empty map, and a constructor with a single argument of type <tt>Map</tt>, 59 * which creates a new map with the same key-value mappings as its argument. 60 * In effect, the latter constructor allows the user to copy any map, 61 * producing an equivalent map of the desired class. There is no way to 62 * enforce this recommendation (as interfaces cannot contain constructors) but 63 * all of the general-purpose map implementations in the JDK comply. 64 * 65 * <p>The "destructive" methods contained in this interface, that is, the 66 * methods that modify the map on which they operate, are specified to throw 67 * <tt>UnsupportedOperationException</tt> if this map does not support the 68 * operation. If this is the case, these methods may, but are not required 69 * to, throw an <tt>UnsupportedOperationException</tt> if the invocation would 70 * have no effect on the map. For example, invoking the {@link #putAll(Map)} 71 * method on an unmodifiable map may, but is not required to, throw the 72 * exception if the map whose mappings are to be "superimposed" is empty. 73 * 74 * <p>Some map implementations have restrictions on the keys and values they 75 * may contain. For example, some implementations prohibit null keys and 76 * values, and some have restrictions on the types of their keys. Attempting 77 * to insert an ineligible key or value throws an unchecked exception, 78 * typically <tt>NullPointerException</tt> or <tt>ClassCastException</tt>. 79 * Attempting to query the presence of an ineligible key or value may throw an 80 * exception, or it may simply return false; some implementations will exhibit 81 * the former behavior and some will exhibit the latter. More generally, 82 * attempting an operation on an ineligible key or value whose completion 83 * would not result in the insertion of an ineligible element into the map may 84 * throw an exception or it may succeed, at the option of the implementation. 85 * Such exceptions are marked as "optional" in the specification for this 86 * interface. 87 * 88 * <p>This interface is a member of the 89 * <a href="{@docRoot}/../technotes/guides/collections/index.html"> 90 * Java Collections Framework</a>. 91 * 92 * <p>Many methods in Collections Framework interfaces are defined 93 * in terms of the {@link Object#equals(Object) equals} method. For 94 * example, the specification for the {@link #containsKey(Object) 95 * containsKey(Object key)} method says: "returns <tt>true</tt> if and 96 * only if this map contains a mapping for a key <tt>k</tt> such that 97 * <tt>(key==null ? k==null : key.equals(k))</tt>." This specification should 98 * <i>not</i> be construed to imply that invoking <tt>Map.containsKey</tt> 99 * with a non-null argument <tt>key</tt> will cause <tt>key.equals(k)</tt> to 100 * be invoked for any key <tt>k</tt>. Implementations are free to 101 * implement optimizations whereby the <tt>equals</tt> invocation is avoided, 102 * for example, by first comparing the hash codes of the two keys. (The 103 * {@link Object#hashCode()} specification guarantees that two objects with 104 * unequal hash codes cannot be equal.) More generally, implementations of 105 * the various Collections Framework interfaces are free to take advantage of 106 * the specified behavior of underlying {@link Object} methods wherever the 107 * implementor deems it appropriate. 108 * 109 * @param <K> the type of keys maintained by this map 110 * @param <V> the type of mapped values 111 * 112 * @author Josh Bloch 113 * @see HashMap 114 * @see TreeMap 115 * @see Hashtable 116 * @see SortedMap 117 * @see Collection 118 * @see Set 119 * @since 1.2 120 */ 121 public interface Map<K,V> { 122 123 // Query Operations 124 125 /** 126 * Returns the number of key-value mappings in this map. If the 127 * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns 128 * <tt>Integer.MAX_VALUE</tt>. 129 * 130 * @return the number of key-value mappings in this map 131 */ 132 int size(); 133 134 /** 135 * Returns <tt>true</tt> if this map contains no key-value mappings. 136 * 137 * @return <tt>true</tt> if this map contains no key-value mappings 138 */ 139 boolean isEmpty(); 140 141 /** 142 * Returns <tt>true</tt> if this map contains a mapping for the specified 143 * key. More formally, returns <tt>true</tt> if and only if 144 * this map contains a mapping for a key <tt>k</tt> such that 145 * <tt>(key==null ? k==null : key.equals(k))</tt>. (There can be 146 * at most one such mapping.) 147 * 148 * @param key key whose presence in this map is to be tested 149 * @return <tt>true</tt> if this map contains a mapping for the specified 150 * key 151 * @throws ClassCastException if the key is of an inappropriate type for 152 * this map 153 * (<a href="Collection.html#optional-restrictions">optional</a>) 154 * @throws NullPointerException if the specified key is null and this map 155 * does not permit null keys 156 * (<a href="Collection.html#optional-restrictions">optional</a>) 157 */ 158 boolean containsKey(Object key); 159 160 /** 161 * Returns <tt>true</tt> if this map maps one or more keys to the 162 * specified value. More formally, returns <tt>true</tt> if and only if 163 * this map contains at least one mapping to a value <tt>v</tt> such that 164 * <tt>(value==null ? v==null : value.equals(v))</tt>. This operation 165 * will probably require time linear in the map size for most 166 * implementations of the <tt>Map</tt> interface. 167 * 168 * @param value value whose presence in this map is to be tested 169 * @return <tt>true</tt> if this map maps one or more keys to the 170 * specified value 171 * @throws ClassCastException if the value is of an inappropriate type for 172 * this map 173 * (<a href="Collection.html#optional-restrictions">optional</a>) 174 * @throws NullPointerException if the specified value is null and this 175 * map does not permit null values 176 * (<a href="Collection.html#optional-restrictions">optional</a>) 177 */ 178 boolean containsValue(Object value); 179 180 /** 181 * Returns the value to which the specified key is mapped, 182 * or {@code null} if this map contains no mapping for the key. 183 * 184 * <p>More formally, if this map contains a mapping from a key 185 * {@code k} to a value {@code v} such that {@code (key==null ? k==null : 186 * key.equals(k))}, then this method returns {@code v}; otherwise 187 * it returns {@code null}. (There can be at most one such mapping.) 188 * 189 * <p>If this map permits null values, then a return value of 190 * {@code null} does not <i>necessarily</i> indicate that the map 191 * contains no mapping for the key; it's also possible that the map 192 * explicitly maps the key to {@code null}. The {@link #containsKey 193 * containsKey} operation may be used to distinguish these two cases. 194 * 195 * @param key the key whose associated value is to be returned 196 * @return the value to which the specified key is mapped, or 197 * {@code null} if this map contains no mapping for the key 198 * @throws ClassCastException if the key is of an inappropriate type for 199 * this map 200 * (<a href="Collection.html#optional-restrictions">optional</a>) 201 * @throws NullPointerException if the specified key is null and this map 202 * does not permit null keys 203 * (<a href="Collection.html#optional-restrictions">optional</a>) 204 */ 205 V get(Object key); 206 207 // Modification Operations 208 209 /** 210 * Associates the specified value with the specified key in this map 211 * (optional operation). If the map previously contained a mapping for 212 * the key, the old value is replaced by the specified value. (A map 213 * <tt>m</tt> is said to contain a mapping for a key <tt>k</tt> if and only 214 * if {@link #containsKey(Object) m.containsKey(k)} would return 215 * <tt>true</tt>.) 216 * 217 * @param key key with which the specified value is to be associated 218 * @param value value to be associated with the specified key 219 * @return the previous value associated with <tt>key</tt>, or 220 * <tt>null</tt> if there was no mapping for <tt>key</tt>. 221 * (A <tt>null</tt> return can also indicate that the map 222 * previously associated <tt>null</tt> with <tt>key</tt>, 223 * if the implementation supports <tt>null</tt> values.) 224 * @throws UnsupportedOperationException if the <tt>put</tt> operation 225 * is not supported by this map 226 * @throws ClassCastException if the class of the specified key or value 227 * prevents it from being stored in this map 228 * @throws NullPointerException if the specified key or value is null 229 * and this map does not permit null keys or values 230 * @throws IllegalArgumentException if some property of the specified key 231 * or value prevents it from being stored in this map 232 */ 233 V put(K key, V value); 234 235 /** 236 * Removes the mapping for a key from this map if it is present 237 * (optional operation). More formally, if this map contains a mapping 238 * from key <tt>k</tt> to value <tt>v</tt> such that 239 * <code>(key==null ? k==null : key.equals(k))</code>, that mapping 240 * is removed. (The map can contain at most one such mapping.) 241 * 242 * <p>Returns the value to which this map previously associated the key, 243 * or <tt>null</tt> if the map contained no mapping for the key. 244 * 245 * <p>If this map permits null values, then a return value of 246 * <tt>null</tt> does not <i>necessarily</i> indicate that the map 247 * contained no mapping for the key; it's also possible that the map 248 * explicitly mapped the key to <tt>null</tt>. 249 * 250 * <p>The map will not contain a mapping for the specified key once the 251 * call returns. 252 * 253 * @param key key whose mapping is to be removed from the map 254 * @return the previous value associated with <tt>key</tt>, or 255 * <tt>null</tt> if there was no mapping for <tt>key</tt>. 256 * @throws UnsupportedOperationException if the <tt>remove</tt> operation 257 * is not supported by this map 258 * @throws ClassCastException if the key is of an inappropriate type for 259 * this map 260 * (<a href="Collection.html#optional-restrictions">optional</a>) 261 * @throws NullPointerException if the specified key is null and this 262 * map does not permit null keys 263 * (<a href="Collection.html#optional-restrictions">optional</a>) 264 */ 265 V remove(Object key); 266 267 268 // Bulk Operations 269 270 /** 271 * Copies all of the mappings from the specified map to this map 272 * (optional operation). The effect of this call is equivalent to that 273 * of calling {@link #put(Object,Object) put(k, v)} on this map once 274 * for each mapping from key <tt>k</tt> to value <tt>v</tt> in the 275 * specified map. The behavior of this operation is undefined if the 276 * specified map is modified while the operation is in progress. 277 * 278 * @param m mappings to be stored in this map 279 * @throws UnsupportedOperationException if the <tt>putAll</tt> operation 280 * is not supported by this map 281 * @throws ClassCastException if the class of a key or value in the 282 * specified map prevents it from being stored in this map 283 * @throws NullPointerException if the specified map is null, or if 284 * this map does not permit null keys or values, and the 285 * specified map contains null keys or values 286 * @throws IllegalArgumentException if some property of a key or value in 287 * the specified map prevents it from being stored in this map 288 */ 289 void putAll(Map<? extends K, ? extends V> m); 290 291 /** 292 * Removes all of the mappings from this map (optional operation). 293 * The map will be empty after this call returns. 294 * 295 * @throws UnsupportedOperationException if the <tt>clear</tt> operation 296 * is not supported by this map 297 */ 298 void clear(); 299 300 301 // Views 302 303 /** 304 * Returns a {@link Set} view of the keys contained in this map. 305 * The set is backed by the map, so changes to the map are 306 * reflected in the set, and vice-versa. If the map is modified 307 * while an iteration over the set is in progress (except through 308 * the iterator's own <tt>remove</tt> operation), the results of 309 * the iteration are undefined. The set supports element removal, 310 * which removes the corresponding mapping from the map, via the 311 * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, 312 * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> 313 * operations. It does not support the <tt>add</tt> or <tt>addAll</tt> 314 * operations. 315 * 316 * @return a set view of the keys contained in this map 317 */ 318 Set<K> keySet(); 319 320 /** 321 * Returns a {@link Collection} view of the values contained in this map. 322 * The collection is backed by the map, so changes to the map are 323 * reflected in the collection, and vice-versa. If the map is 324 * modified while an iteration over the collection is in progress 325 * (except through the iterator's own <tt>remove</tt> operation), 326 * the results of the iteration are undefined. The collection 327 * supports element removal, which removes the corresponding 328 * mapping from the map, via the <tt>Iterator.remove</tt>, 329 * <tt>Collection.remove</tt>, <tt>removeAll</tt>, 330 * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not 331 * support the <tt>add</tt> or <tt>addAll</tt> operations. 332 * 333 * @return a collection view of the values contained in this map 334 */ 335 Collection<V> values(); 336 337 /** 338 * Returns a {@link Set} view of the mappings contained in this map. 339 * The set is backed by the map, so changes to the map are 340 * reflected in the set, and vice-versa. If the map is modified 341 * while an iteration over the set is in progress (except through 342 * the iterator's own <tt>remove</tt> operation, or through the 343 * <tt>setValue</tt> operation on a map entry returned by the 344 * iterator) the results of the iteration are undefined. The set 345 * supports element removal, which removes the corresponding 346 * mapping from the map, via the <tt>Iterator.remove</tt>, 347 * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and 348 * <tt>clear</tt> operations. It does not support the 349 * <tt>add</tt> or <tt>addAll</tt> operations. 350 * 351 * @return a set view of the mappings contained in this map 352 */ 353 Set<Map.Entry<K, V>> entrySet(); 354 355 /** 356 * A map entry (key-value pair). The <tt>Map.entrySet</tt> method returns 357 * a collection-view of the map, whose elements are of this class. The 358 * <i>only</i> way to obtain a reference to a map entry is from the 359 * iterator of this collection-view. These <tt>Map.Entry</tt> objects are 360 * valid <i>only</i> for the duration of the iteration; more formally, 361 * the behavior of a map entry is undefined if the backing map has been 362 * modified after the entry was returned by the iterator, except through 363 * the <tt>setValue</tt> operation on the map entry. 364 * 365 * @see Map#entrySet() 366 * @since 1.2 367 */ 368 interface Entry<K,V> { 369 /** 370 * Returns the key corresponding to this entry. 371 * 372 * @return the key corresponding to this entry 373 * @throws IllegalStateException implementations may, but are not 374 * required to, throw this exception if the entry has been 375 * removed from the backing map. 376 */ 377 K getKey(); 378 379 /** 380 * Returns the value corresponding to this entry. If the mapping 381 * has been removed from the backing map (by the iterator's 382 * <tt>remove</tt> operation), the results of this call are undefined. 383 * 384 * @return the value corresponding to this entry 385 * @throws IllegalStateException implementations may, but are not 386 * required to, throw this exception if the entry has been 387 * removed from the backing map. 388 */ 389 V getValue(); 390 391 /** 392 * Replaces the value corresponding to this entry with the specified 393 * value (optional operation). (Writes through to the map.) The 394 * behavior of this call is undefined if the mapping has already been 395 * removed from the map (by the iterator's <tt>remove</tt> operation). 396 * 397 * @param value new value to be stored in this entry 398 * @return old value corresponding to the entry 399 * @throws UnsupportedOperationException if the <tt>put</tt> operation 400 * is not supported by the backing map 401 * @throws ClassCastException if the class of the specified value 402 * prevents it from being stored in the backing map 403 * @throws NullPointerException if the backing map does not permit 404 * null values, and the specified value is null 405 * @throws IllegalArgumentException if some property of this value 406 * prevents it from being stored in the backing map 407 * @throws IllegalStateException implementations may, but are not 408 * required to, throw this exception if the entry has been 409 * removed from the backing map. 410 */ 411 V setValue(V value); 412 413 /** 414 * Compares the specified object with this entry for equality. 415 * Returns <tt>true</tt> if the given object is also a map entry and 416 * the two entries represent the same mapping. More formally, two 417 * entries <tt>e1</tt> and <tt>e2</tt> represent the same mapping 418 * if<pre> 419 * (e1.getKey()==null ? 420 * e2.getKey()==null : e1.getKey().equals(e2.getKey())) && 421 * (e1.getValue()==null ? 422 * e2.getValue()==null : e1.getValue().equals(e2.getValue())) 423 * </pre> 424 * This ensures that the <tt>equals</tt> method works properly across 425 * different implementations of the <tt>Map.Entry</tt> interface. 426 * 427 * @param o object to be compared for equality with this map entry 428 * @return <tt>true</tt> if the specified object is equal to this map 429 * entry 430 */ 431 boolean equals(Object o); 432 433 /** 434 * Returns the hash code value for this map entry. The hash code 435 * of a map entry <tt>e</tt> is defined to be: <pre> 436 * (e.getKey()==null ? 0 : e.getKey().hashCode()) ^ 437 * (e.getValue()==null ? 0 : e.getValue().hashCode()) 438 * </pre> 439 * This ensures that <tt>e1.equals(e2)</tt> implies that 440 * <tt>e1.hashCode()==e2.hashCode()</tt> for any two Entries 441 * <tt>e1</tt> and <tt>e2</tt>, as required by the general 442 * contract of <tt>Object.hashCode</tt>. 443 * 444 * @return the hash code value for this map entry 445 * @see Object#hashCode() 446 * @see Object#equals(Object) 447 * @see #equals(Object) 448 */ 449 int hashCode(); 450 } 451 452 // Comparison and hashing 453 454 /** 455 * Compares the specified object with this map for equality. Returns 456 * <tt>true</tt> if the given object is also a map and the two maps 457 * represent the same mappings. More formally, two maps <tt>m1</tt> and 458 * <tt>m2</tt> represent the same mappings if 459 * <tt>m1.entrySet().equals(m2.entrySet())</tt>. This ensures that the 460 * <tt>equals</tt> method works properly across different implementations 461 * of the <tt>Map</tt> interface. 462 * 463 * @param o object to be compared for equality with this map 464 * @return <tt>true</tt> if the specified object is equal to this map 465 */ 466 boolean equals(Object o); 467 468 /** 469 * Returns the hash code value for this map. The hash code of a map is 470 * defined to be the sum of the hash codes of each entry in the map's 471 * <tt>entrySet()</tt> view. This ensures that <tt>m1.equals(m2)</tt> 472 * implies that <tt>m1.hashCode()==m2.hashCode()</tt> for any two maps 473 * <tt>m1</tt> and <tt>m2</tt>, as required by the general contract of 474 * {@link Object#hashCode}. 475 * 476 * @return the hash code value for this map 477 * @see Map.Entry#hashCode() 478 * @see Object#equals(Object) 479 * @see #equals(Object) 480 */ 481 int hashCode(); 482 483 // Defaultable methods 484 485 /** 486 * Execute the specified {@code BiConsumer} with the key and value of 487 * each entry in this map. 488 * 489 * @param block the {@code BiConsumer} to which entries will be applied 490 */ 491 default void forEach(BiConsumer<? super K, ? super V> block) { 492 Objects.requireNonNull(block); 493 for (Map.Entry<K, V> entry : entrySet()) { 494 block.accept(entry.getKey(), entry.getValue()); 495 } 496 } 497 498 /** 499 * Apply the specified function to each entry in this map, replacing 500 * each entry's value with the result of calling the function's 501 * {@link BiFunction#apply(Object, Object) BiFunction.apply(K key, V, value)} 502 * method with the current entry's key and value. 503 * 504 * @param function the function to apply to each entry 505 */ 506 default void replaceAll(BiFunction<K, V, V> function) { 507 Objects.requireNonNull(function); 508 for (Map.Entry<K, V> entry : entrySet()) { 509 entry.setValue(function.apply(entry.getKey(), entry.getValue())); 510 } 511 } 512 513 /** 514 * If the specified key is not already associated with a value, 515 * associates it with the given value and returns {@code null}, 516 * else returns the current value. 517 * 518 * <p>The default implementation is equivalent to, for this {@code 519 * map}: 520 * 521 * <pre> {@code 522 * if (!map.containsKey(key)) 523 * return map.put(key, value); 524 * else 525 * return map.get(key);}</pre> 526 * 527 * <p>The default implementation makes no guarantees about 528 * synchronization or atomicity properties of this method. Any 529 * class overriding this method must specify its concurrency 530 * properties. In particular, all implementations of 531 * subinterface {@link java.util.concurrent.ConcurrentMap} 532 * must ensure that this operation is performed atomically. 533 * 534 * @param key key with which the specified value is to be associated 535 * @param value value to be associated with the specified key 536 * @return the previous value associated with the specified key, or 537 * <tt>null</tt> if there was no mapping for the key. 538 * (A <tt>null</tt> return can also indicate that the map 539 * previously associated <tt>null</tt> with the key, 540 * if the implementation supports null values.) 541 * @throws UnsupportedOperationException if the <tt>put</tt> operation 542 * is not supported by this map 543 * @throws ClassCastException if the class of the specified key or value 544 * prevents it from being stored in this map 545 * @throws NullPointerException if the specified key or value is null, 546 * and this map does not permit null keys or values 547 * @throws IllegalArgumentException if some property of the specified key 548 * or value prevents it from being stored in this map 549 */ 550 default V putIfAbsent(K key, V value) { 551 return containsKey(key) ? get(key) : put(key, value); 552 } 553 554 /** 555 * Removes the entry for the specified key only if it is currently 556 * mapped to the specified value. 557 * 558 * <p>The default implementation is equivalent to, for this {@code map}: 559 * 560 * <pre> {@code 561 * if (map.containsKey(key) && map.get(key).equals(value)) { 562 * map.remove(key); 563 * return true; 564 * } else 565 * return false;}</pre> 566 * 567 * <p>The default implementation makes no guarantees about 568 * synchronization or atomicity properties of this method. Any 569 * class overriding this method must specify its concurrency 570 * properties. In particular, all implementations of 571 * subinterface {@link java.util.concurrent.ConcurrentMap} 572 * must ensure that this operation is performed atomically. 573 * 574 * @param key key with which the specified value is associated 575 * @param value value expected to be associated with the specified key 576 * @return <tt>true</tt> if the value was removed 577 * @throws UnsupportedOperationException if the <tt>remove</tt> operation 578 * is not supported by this map 579 * @throws ClassCastException if the key or value is of an inappropriate 580 * type for this map 581 * (<a href="Collection.html#optional-restrictions">optional</a>) 582 * @throws NullPointerException if the specified key or value is null, 583 * and this map does not permit null keys or values 584 * (<a href="Collection.html#optional-restrictions">optional</a>) 585 */ 586 default boolean remove(Object key, Object value) { 587 if (!containsKey(key) || !get(key).equals(value)) 588 return false; 589 remove(key); 590 return true; 591 } 592 593 /** 594 * Replaces the entry for the specified key only if currently 595 * mapped to the specified value. 596 * 597 * <p>The default implementation is equivalent to, for this {@code map}: 598 * 599 * <pre> {@code 600 * if (map.containsKey(key) && map.get(key).equals(oldValue)) { 601 * map.put(key, newValue); 602 * return true; 603 * } else 604 * return false;}</pre> 605 * 606 * <p>The default implementation makes no guarantees about 607 * synchronization or atomicity properties of this method. Any 608 * class overriding this method must specify its concurrency 609 * properties. In particular, all implementations of 610 * subinterface {@link java.util.concurrent.ConcurrentMap} 611 * must ensure that this operation is performed atomically. 612 * 613 * @param key key with which the specified value is associated 614 * @param oldValue value expected to be associated with the specified key 615 * @param newValue value to be associated with the specified key 616 * @return <tt>true</tt> if the value was replaced 617 * @throws UnsupportedOperationException if the <tt>put</tt> operation 618 * is not supported by this map 619 * @throws ClassCastException if the class of a specified key or value 620 * prevents it from being stored in this map 621 * @throws NullPointerException if a specified key or value is null, 622 * and this map does not permit null keys or values 623 * @throws IllegalArgumentException if some property of a specified key 624 * or value prevents it from being stored in this map 625 */ 626 default boolean replace(K key, V oldValue, V newValue) { 627 if (!containsKey(key) || !get(key).equals(oldValue)) 628 return false; 629 put(key, newValue); 630 return true; 631 } 632 633 /** 634 * Replaces the entry for the specified key only if it is 635 * currently mapped to some value. 636 * 637 * <p>The default implementation is equivalent to, for this {@code map}: 638 * 639 * <pre> {@code 640 * if (map.containsKey(key)) { 641 * return map.put(key, value); 642 * } else 643 * return null;}</pre> 644 * 645 * <p>The default implementation makes no guarantees about 646 * synchronization or atomicity properties of this method. Any 647 * class overriding this method must specify its concurrency 648 * properties. In particular, all implementations of 649 * subinterface {@link java.util.concurrent.ConcurrentMap} 650 * must ensure that this operation is performed atomically. 651 * 652 * @param key key with which the specified value is associated 653 * @param value value to be associated with the specified key 654 * @return the previous value associated with the specified key, or 655 * <tt>null</tt> if there was no mapping for the key. 656 * (A <tt>null</tt> return can also indicate that the map 657 * previously associated <tt>null</tt> with the key, 658 * if the implementation supports null values.) 659 * @throws UnsupportedOperationException if the <tt>put</tt> operation 660 * is not supported by this map 661 * @throws ClassCastException if the class of the specified key or value 662 * prevents it from being stored in this map 663 * @throws NullPointerException if the specified key or value is null, 664 * and this map does not permit null keys or values 665 * @throws IllegalArgumentException if some property of the specified key 666 * or value prevents it from being stored in this map 667 */ 668 default V replace(K key, V value) { 669 return containsKey(key) ? put(key, value) : null; 670 } 671 672 /** 673 * If the specified key is not already associated with a value (or 674 * is mapped to {@code null}), attempts to compute its value using 675 * the given mapping function and enters it into this map unless 676 * {@code null}. 677 * 678 * <p>The default implementation is equivalent to the following 679 * steps for this {@code map}, then returning the current value or 680 * {@code null} if now absent: 681 * 682 * <pre> {@code 683 * if (map.get(key) == null) { 684 * V newValue = mappingFunction.apply(key); 685 * if (newValue != null) 686 * map.putIfAbsent(key, newValue); 687 * }}</pre> 688 * 689 * If the function returns {@code null} no mapping is recorded. If 690 * the function itself throws an (unchecked) exception, the 691 * exception is rethrown, and no mapping is recorded. The most 692 * common usage is to construct a new object serving as an initial 693 * mapped value or memoized result, as in: 694 * 695 * <pre> {@code 696 * map.computeIfAbsent(key, k -> new Value(f(k)));}</pre> 697 * 698 * <p>The default implementation makes no guarantees about 699 * synchronization or atomicity properties of this method or the 700 * application of the mapping function. Any class overriding this 701 * method must specify its concurrency properties. In particular, 702 * all implementations of subinterface {@link 703 * java.util.concurrent.ConcurrentMap} must document whether the 704 * function is applied once atomically only if the value is not 705 * present. Any class that permits null values must document 706 * whether and how this method distinguishes absence from null 707 * mappings. 708 * 709 * @param key key with which the specified value is to be associated 710 * @param mappingFunction the function to compute a value 711 * @return the current (existing or computed) value associated with 712 * the specified key, or null if the computed value is null 713 * @throws NullPointerException if the specified key is null and 714 * this map does not support null keys, or the 715 * mappingFunction is null 716 * @throws UnsupportedOperationException if the <tt>put</tt> operation 717 * is not supported by this map 718 * @throws ClassCastException if the class of the specified key or value 719 * prevents it from being stored in this map 720 * @throws RuntimeException or Error if the mappingFunction does so, 721 * in which case the mapping is left unestablished 722 */ 723 default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { 724 V v, newValue; 725 return ((v = get(key)) == null && 726 (newValue = mappingFunction.apply(key)) != null && 727 (v = putIfAbsent(key, newValue)) == null) ? newValue : v; 728 } 729 730 /** 731 * If the value for the specified key is present and non-null, 732 * attempts to compute a new mapping given the key and its current 733 * mapped value. 734 * 735 * <p>The default implementation is equivalent to performing the 736 * following steps for this {@code map}, then returning the 737 * current value or {@code null} if now absent: 738 * 739 * <pre> {@code 740 * if (map.get(key) != null) { 741 * V oldValue = map.get(key); 742 * V newValue = remappingFunction.apply(key, oldValue); 743 * if (newValue != null) 744 * map.replace(key, oldValue, newValue); 745 * else 746 * map.remove(key, oldValue); 747 * }}</pre> 748 * 749 * In concurrent contexts, the default implementation may retry 750 * these steps when multiple threads attempt updates. If the 751 * function returns {@code null}, the mapping is removed (or 752 * remains absent if initially absent). If the function itself 753 * throws an (unchecked) exception, the exception is rethrown, and 754 * the current mapping is left unchanged. 755 * 756 * <p>The default implementation makes no guarantees about 757 * synchronization or atomicity properties of this method or the 758 * application of the remapping function. Any class overriding 759 * this method must specify its concurrency properties. In 760 * particular, all implementations of subinterface {@link 761 * java.util.concurrent.ConcurrentMap} must document whether the 762 * function is applied once atomically only if the value is 763 * present. Any class that permits null values must document 764 * whether and how this method distinguishes absence from null 765 * mappings. 766 * 767 * @param key key with which the specified value is to be associated 768 * @param remappingFunction the function to compute a value 769 * @return the new value associated with the specified key, or null if none 770 * @throws NullPointerException if the specified key is null and 771 * this map does not support null keys, or the 772 * remappingFunction is null 773 * @throws UnsupportedOperationException if the <tt>put</tt> operation 774 * is not supported by this map 775 * @throws ClassCastException if the class of the specified key or value 776 * prevents it from being stored in this map 777 * @throws RuntimeException or Error if the remappingFunction does so, 778 * in which case the mapping is unchanged 779 */ 780 default V computeIfPresent(K key, 781 BiFunction<? super K, ? super V, ? extends V> remappingFunction) { 782 V v; 783 while ((v = get(key)) != null) { 784 V newValue = remappingFunction.apply(key, v); 785 if (newValue != null) { 786 if (replace(key, v, newValue)) 787 return newValue; 788 } 789 else if (remove(key, v)) 790 return null; 791 } 792 return v; 793 } 794 795 /** 796 * Attempts to compute a mapping for the specified key and its 797 * current mapped value (or {@code null} if there is no current 798 * mapping). For example, to either create or append a {@code 799 * String msg} to a value mapping: 800 * 801 * <pre> {@code 802 * map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg))}</pre> 803 * (Method {@link #merge} is often simpler to use for such purposes.) 804 * 805 * <p>The default implementation is equivalent to 806 * performing the following steps for this {@code map}, then 807 * returning the current value or {@code null} if absent: 808 * 809 * <pre> {@code 810 * V oldValue = map.get(key); 811 * V newValue = remappingFunction.apply(key, oldValue); 812 * if (newValue != null) 813 * map.replace(key, oldValue, newValue); 814 * else 815 * map.remove(key, oldValue); 816 * }</pre> 817 * 818 * In concurrent contexts, the default implementation may retry 819 * these steps when multiple threads attempt updates. If the 820 * function returns {@code null}, the mapping is removed (or 821 * remains absent if initially absent). If the function itself 822 * throws an (unchecked) exception, the exception is rethrown, and 823 * the current mapping is left unchanged. 824 * 825 * <p>The default implementation makes no guarantees about 826 * synchronization or atomicity properties of this method or the 827 * application of the remapping function. Any class overriding 828 * this method must specify its concurrency properties. In 829 * particular, all implementations of subinterface {@link 830 * java.util.concurrent.ConcurrentMap} must document whether the 831 * function is applied exactly once atomically. Any class that 832 * permits null values must document whether and how this method 833 * distinguishes absence from null mappings. 834 * 835 * @param key key with which the specified value is to be associated 836 * @param remappingFunction the function to compute a value 837 * @return the new value associated with the specified key, or null if none 838 * @throws NullPointerException if the specified key is null and 839 * this map does not support null keys, or the 840 * remappingFunction is null 841 * @throws UnsupportedOperationException if the <tt>put</tt> operation 842 * is not supported by this map 843 * @throws ClassCastException if the class of the specified key or value 844 * prevents it from being stored in this map 845 * @throws RuntimeException or Error if the remappingFunction does so, 846 * in which case the mapping is unchanged 847 */ 848 default V compute(K key, 849 BiFunction<? super K, ? super V, ? extends V> remappingFunction) { 850 for (;;) { 851 V oldValue = get(key); 852 V newValue = remappingFunction.apply(key, oldValue); 853 if (newValue != null) { 854 if (replace(key, oldValue, newValue)) 855 return newValue; 856 } 857 else if (remove(key, oldValue)) 858 return null; 859 } 860 } 861 862 /** 863 * If the specified key is not already associated with a 864 * (non-null) value, associates it with the given value. 865 * Otherwise, replaces the value with the results of the given 866 * remapping function, or removes if {@code null}. This method may 867 * be of use when combining multiple mapped values for a key. For 868 * example. to either create or append a {@code String msg} to a 869 * value mapping: 870 * 871 * <pre> {@code 872 * map.merge(key, msg, String::concat)}</pre> 873 * 874 * <p>The default implementation is equivalent to performing the 875 * following steps for this {@code map}, then returning the 876 * current value or {@code null} if absent: 877 * 878 * <pre> {@code 879 * V oldValue = map.get(key); 880 * V newValue = (oldValue == null) ? value : 881 * remappingFunction.apply(oldValue, value); 882 * if (newValue == null) 883 * map.remove(key, oldValue); 884 * else if (oldValue == null) 885 * map.putIfAbsent(key, newValue); 886 * else 887 * map.replace(key, oldValue, newValue); 888 * }</pre> 889 * 890 * In concurrent contexts, the default implementation may retry 891 * these steps when multiple threads attempt updates. If the 892 * function returns {@code null}, the mapping is removed (or 893 * remains absent if initially absent). If the function itself 894 * throws an (unchecked) exception, the exception is rethrown, and 895 * the current mapping is left unchanged. 896 * 897 * <p>The default implementation makes no guarantees about 898 * synchronization or atomicity properties of this method or the 899 * application of the remapping function. Any class overriding 900 * this method must specify its concurrency properties. In 901 * particular, all implementations of subinterface {@link 902 * java.util.concurrent.ConcurrentMap} must document whether the 903 * function is applied exactly once atomically. Any class that 904 * permits null values must document whether and how this method 905 * distinguishes absence from null mappings. 906 * 907 * @param key key with which the specified value is to be associated 908 * @param value the value to use if absent 909 * @param remappingFunction the function to recompute a value if present 910 * @return the new value associated with the specified key, or null if none 911 * @throws NullPointerException if the specified key is null and 912 * this map does not support null keys, or the 913 * remappingFunction is null 914 * @throws RuntimeException or Error if the remappingFunction does so, 915 * in which case the mapping is unchanged 916 */ 917 default V merge(K key, V value, 918 BiFunction<? super V, ? super V, ? extends V> remappingFunction) { 919 for (;;) { 920 V oldValue, newValue; 921 if ((oldValue = get(key)) == null) { 922 if (value == null || putIfAbsent(key, value) == null) 923 return value; 924 } 925 else if ((newValue = remappingFunction.apply(oldValue, value)) != null) { 926 if (replace(key, oldValue, newValue)) 927 return newValue; 928 } 929 else if (remove(key, oldValue)) 930 return null; 931 } 932 } 933 }