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 /**
29 * An object that maps keys to values. A map cannot contain duplicate keys;
30 * each key can map to at most one value.
31 *
32 * <p>This interface takes the place of the <tt>Dictionary</tt> class, which
33 * was a totally abstract class rather than an interface.
34 *
35 * <p>The <tt>Map</tt> interface provides three <i>collection views</i>, which
36 * allow a map's contents to be viewed as a set of keys, collection of values,
37 * or set of key-value mappings. The <i>order</i> of a map is defined as
38 * the order in which the iterators on the map's collection views return their
39 * elements. Some map implementations, like the <tt>TreeMap</tt> class, make
40 * specific guarantees as to their order; others, like the <tt>HashMap</tt>
41 * class, do not.
42 *
43 * <p>Note: great care must be exercised if mutable objects are used as map
44 * keys. The behavior of a map is not specified if the value of an object is
45 * changed in a manner that affects <tt>equals</tt> comparisons while the
46 * object is a key in the map. A special case of this prohibition is that it
47 * is not permissible for a map to contain itself as a key. While it is
458 * @param o object to be compared for equality with this map
459 * @return <tt>true</tt> if the specified object is equal to this map
460 */
461 boolean equals(Object o);
462
463 /**
464 * Returns the hash code value for this map. The hash code of a map is
465 * defined to be the sum of the hash codes of each entry in the map's
466 * <tt>entrySet()</tt> view. This ensures that <tt>m1.equals(m2)</tt>
467 * implies that <tt>m1.hashCode()==m2.hashCode()</tt> for any two maps
468 * <tt>m1</tt> and <tt>m2</tt>, as required by the general contract of
469 * {@link Object#hashCode}.
470 *
471 * @return the hash code value for this map
472 * @see Map.Entry#hashCode()
473 * @see Object#equals(Object)
474 * @see #equals(Object)
475 */
476 int hashCode();
477
478 }
|
1 /*
2 * Copyright (c) 1997, 2013, 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
462 * @param o object to be compared for equality with this map
463 * @return <tt>true</tt> if the specified object is equal to this map
464 */
465 boolean equals(Object o);
466
467 /**
468 * Returns the hash code value for this map. The hash code of a map is
469 * defined to be the sum of the hash codes of each entry in the map's
470 * <tt>entrySet()</tt> view. This ensures that <tt>m1.equals(m2)</tt>
471 * implies that <tt>m1.hashCode()==m2.hashCode()</tt> for any two maps
472 * <tt>m1</tt> and <tt>m2</tt>, as required by the general contract of
473 * {@link Object#hashCode}.
474 *
475 * @return the hash code value for this map
476 * @see Map.Entry#hashCode()
477 * @see Object#equals(Object)
478 * @see #equals(Object)
479 */
480 int hashCode();
481
482 // Defaultable methods
483
484 /**
485 * Returns the value to which the specified key is mapped,
486 * or {@code defaultValue} if this map contains no mapping
487 * for the key.
488 *
489 * @param key the key whose associated value is to be returned
490 * @return the value to which the specified key is mapped, or
491 * {@code defaultValue} if this map contains no mapping for the key
492 * @throws ClassCastException if the key is of an inappropriate type for
493 * this map
494 * (<a href="Collection.html#optional-restrictions">optional</a>)
495 * @throws NullPointerException if the specified key is null and this map
496 * does not permit null keys
497 * (<a href="Collection.html#optional-restrictions">optional</a>)
498 */
499 default V getOrDefault(Object key, V defaultValue) {
500 V v;
501 return (((v = get(key)) != null) || containsKey(key))
502 ? v
503 : defaultValue;
504 }
505
506 /**
507 * Performs the given action on each entry in this map, in the
508 * order entries are returned by an entry set iterator, until all entries
509 * have been processed or the action throws an {@code Exception}.
510 * Exceptions thrown by the action are relayed to the caller.
511 *
512 * <p>The default implementation should be overridden by implementations if
513 * they can provide a more performant implementation than an iterator-based
514 * one.
515 *
516 * <p>The default implementation makes no guarantees about synchronization
517 * or atomicity properties of this method. Any class which wishes to provide
518 * specific synchronization, atomicity or concurrency behaviour should
519 * override this method.
520 *
521 * @implSpec The default implementation is equivalent to, for this
522 * {@code map}:
523 * <pre> {@code
524 * for ((Map.Entry<K, V> entry : map.entrySet())
525 * action.accept(entry.getKey(), entry.getValue());
526 * }</pre>
527 *
528 * @param action The action to be performed for each entry
529 * @throws NullPointerException if the specified action is null
530 * @throws ConcurrentModificationException if an entry is found to be
531 * removed during iteration
532 * @since 1.8
533 */
534 default void forEach(BiConsumer<? super K, ? super V> action) {
535 Objects.requireNonNull(action);
536 for (Map.Entry<K, V> entry : entrySet()) {
537 K k;
538 V v;
539 try {
540 k = entry.getKey();
541 v = entry.getValue();
542 } catch(IllegalStateException ise) {
543 throw new ConcurrentModificationException(ise);
544 }
545 action.accept(k, v);
546 }
547 }
548
549 /**
550 * Replaces each entry's value with the result of invoking the given
551 * function on that entry, in the order entries are returned by an entry
552 * set iterator, until all entries have been processed or the function
553 * throws an exception.
554 *
555 * <p>The default implementation makes no guarantees about synchronization
556 * or atomicity properties of this method. Any class which wishes to provide
557 * specific synchronization, atomicity or concurrency behaviour should
558 * override this method.
559 *
560 * @implSpec
561 * <p>The default implementation is equivalent to, for this {@code map}:
562 * <pre> {@code
563 * for ((Map.Entry<K, V> entry : map.entrySet())
564 * entry.setValue(function.apply(entry.getKey(), entry.getValue()));
565 * }</pre>
566 *
567 * @param function the function to apply to each entry
568 * @throws UnsupportedOperationException if the <tt>set</tt> operation
569 * is not supported by this map's entry set iterator.
570 * @throws ClassCastException if the class of a replacement value
571 * prevents it from being stored in this map
572 * @throws NullPointerException if the specified function is null, or the
573 * specified replacement value is null, and this map does not permit null
574 * values
575 * @throws ClassCastException if a replacement value is of an inappropriate
576 * type for this map
577 * (<a href="Collection.html#optional-restrictions">optional</a>)
578 * @throws NullPointerException if function or a replacement value is null,
579 * and this map does not permit null keys or values
580 * (<a href="Collection.html#optional-restrictions">optional</a>)
581 * @throws IllegalArgumentException if some property of a replacement value
582 * prevents it from being stored in this map
583 * (<a href="Collection.html#optional-restrictions">optional</a>)
584 * @throws ConcurrentModificationException if an entry is found to be
585 * removed during iteration
586 * @since 1.8
587 */
588 default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
589 Objects.requireNonNull(function);
590 for (Map.Entry<K, V> entry : entrySet()) {
591 K k;
592 V v;
593 try {
594 k = entry.getKey();
595 v = entry.getValue();
596 } catch(IllegalStateException ise) {
597 throw new ConcurrentModificationException(ise);
598 }
599 entry.setValue(function.apply(k, v));
600 }
601 }
602
603 /**
604 * If the specified key is not already associated with a value (or is mapped
605 * to {@code null}) associates it with the given value and returns
606 * {@code null}, else returns the current value.
607 *
608 * <p>The default implementation makes no guarantees about
609 * synchronization or atomicity properties of this method. Any
610 * class overriding this method must specify its concurrency
611 * properties. In particular, all implementations of
612 * subinterface {@link java.util.concurrent.ConcurrentMap}
613 * must ensure that this operation is performed atomically.
614 *
615 * @implSpec
616 * The default implementation is equivalent to, for this {@code
617 * map}:
618 *
619 * <pre> {@code
620 * if (map.get(key) == null)
621 * return map.put(key, value);
622 * else
623 * return map.get(key);}</pre>
624 *
625 * @param key key with which the specified value is to be associated
626 * @param value value to be associated with the specified key
627 * @return the previous value associated with the specified key, or
628 * {@code 1} if there was no mapping for the key.
629 * (A <tt>null</tt> return can also indicate that the map
630 * previously associated <tt>null</tt> with the key,
631 * if the implementation supports null values.)
632 * @throws UnsupportedOperationException if the <tt>put</tt> operation
633 * is not supported by this map
634 * (<a href="Collection.html#optional-restrictions">optional</a>)
635 * @throws ClassCastException if the key or value is of an inappropriate
636 * type for this map
637 * (<a href="Collection.html#optional-restrictions">optional</a>)
638 * @throws NullPointerException if the specified key or value is null,
639 * and this map does not permit null keys or values
640 * (<a href="Collection.html#optional-restrictions">optional</a>)
641 * @throws IllegalArgumentException if some property of the specified key
642 * or value prevents it from being stored in this map
643 * (<a href="Collection.html#optional-restrictions">optional</a>)
644 * @throws ConcurrentModificationException if a modification of the map is
645 * detected during insertion of the value.
646 * @since 1.8
647 */
648 default V putIfAbsent(K key, V value) {
649 V v = get(key);
650 if (v == null) {
651 if (put(key, value) != null) {
652 throw new ConcurrentModificationException();
653 }
654 }
655
656 return v;
657 }
658
659 /**
660 * Removes the entry for the specified key only if it is currently
661 * mapped to the specified value.
662 *
663 * <p>The default implementation makes no guarantees about
664 * synchronization or atomicity properties of this method. Any
665 * class overriding this method must specify its concurrency
666 * properties. In particular, all implementations of
667 * subinterface {@link java.util.concurrent.ConcurrentMap}
668 * must ensure that this operation is performed atomically.
669 *
670 * @implSpec
671 * The default implementation is equivalent to, for this {@code map}:
672 *
673 * <pre> {@code
674 * if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
675 * map.remove(key);
676 * return true;
677 * } else
678 * return false;}</pre>
679 *
680 * @param key key with which the specified value is associated
681 * @param value value expected to be associated with the specified key
682 * @return <tt>true</tt> if the value was removed
683 * @throws UnsupportedOperationException if the <tt>remove</tt> operation
684 * is not supported by this map
685 * (<a href="Collection.html#optional-restrictions">optional</a>)
686 * @throws ClassCastException if the key or value is of an inappropriate
687 * type for this map
688 * (<a href="Collection.html#optional-restrictions">optional</a>)
689 * @throws NullPointerException if the specified key or value is null,
690 * and this map does not permit null keys or values
691 * (<a href="Collection.html#optional-restrictions">optional</a>)
692 * @since 1.8
693 */
694 default boolean remove(Object key, Object value) {
695 if (!Objects.equals(get(key), value) || !containsKey(key))
696 return false;
697 remove(key);
698 return true;
699 }
700
701 /**
702 * Replaces the entry for the specified key only if currently
703 * mapped to the specified value.
704 *
705 * <p>The default implementation makes no guarantees about
706 * synchronization or atomicity properties of this method. Any
707 * class overriding this method must specify its concurrency
708 * properties. In particular, all implementations of
709 * subinterface {@link java.util.concurrent.ConcurrentMap}
710 * must ensure that this operation is performed atomically.
711 *
712 * @implSpec
713 * The default implementation is equivalent to, for this {@code map}:
714 *
715 * <pre> {@code
716 * if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
717 * map.put(key, newValue);
718 * return true;
719 * } else
720 * return false;}</pre>
721 *
722 * @param key key with which the specified value is associated
723 * @param oldValue value expected to be associated with the specified key
724 * @param newValue value to be associated with the specified key
725 * @return <tt>true</tt> if the value was replaced
726 * @throws UnsupportedOperationException if the <tt>put</tt> operation
727 * is not supported by this map
728 * (<a href="Collection.html#optional-restrictions">optional</a>)
729 * @throws ClassCastException if the class of a specified key or value
730 * prevents it from being stored in this map
731 * @throws NullPointerException if a specified key or value is null,
732 * and this map does not permit null keys or values
733 * @throws IllegalArgumentException if some property of a specified key
734 * or value prevents it from being stored in this map
735 * @since 1.8
736 */
737 default boolean replace(K key, V oldValue, V newValue) {
738 if (!containsKey(key) || !Objects.equals(get(key), oldValue))
739 return false;
740 put(key, newValue);
741 return true;
742 }
743
744 /**
745 * Replaces the entry for the specified key only if it is
746 * currently mapped to some value.
747 *
748 * <p>The default implementation makes no guarantees about
749 * synchronization or atomicity properties of this method. Any
750 * class overriding this method must specify its concurrency
751 * properties. In particular, all implementations of
752 * subinterface {@link java.util.concurrent.ConcurrentMap}
753 * must ensure that this operation is performed atomically.
754 *
755 * @implSpec
756 * The default implementation is equivalent to, for this {@code map}:
757 *
758 * <pre> {@code
759 * if (map.containsKey(key)) {
760 * return map.put(key, value);
761 * } else
762 * return null;}</pre>
763 *
764 * @param key key with which the specified value is associated
765 * @param value value to be associated with the specified key
766 * @return the previous value associated with the specified key, or
767 * <tt>null</tt> if there was no mapping for the key.
768 * (A <tt>null</tt> return can also indicate that the map
769 * previously associated <tt>null</tt> with the key,
770 * if the implementation supports null values.)
771 * @throws UnsupportedOperationException if the <tt>put</tt> operation
772 * is not supported by this map
773 * (<a href="Collection.html#optional-restrictions">optional</a>)
774 * @throws ClassCastException if the class of the specified key or value
775 * prevents it from being stored in this map
776 * (<a href="Collection.html#optional-restrictions">optional</a>)
777 * @throws NullPointerException if the specified key or value is null,
778 * and this map does not permit null keys or values
779 * @throws IllegalArgumentException if some property of the specified key
780 * or value prevents it from being stored in this map
781 * @since 1.8
782 */
783 default V replace(K key, V value) {
784 return containsKey(key) ? put(key, value) : null;
785 }
786
787 /**
788 * If the specified key is not already associated with a value (or
789 * is mapped to {@code null}), attempts to compute its value using
790 * the given mapping function and enters it into this map unless
791 * {@code null}.
792 *
793 * <p>If the function returns {@code null} no mapping is recorded. If
794 * the function itself throws an (unchecked) exception, the
795 * exception is rethrown, and no mapping is recorded. The most
796 * common usage is to construct a new object serving as an initial
797 * mapped value or memoized result, as in:
798 *
799 * <pre> {@code
800 * map.computeIfAbsent(key, k -> new Value(f(k)));}</pre>
801 *
802 * <p>The default implementation makes no guarantees about
803 * synchronization or atomicity properties of this method or the
804 * application of the mapping function. Any class overriding this
805 * method must specify its concurrency properties. In particular,
806 * all implementations of subinterface {@link
807 * java.util.concurrent.ConcurrentMap} must document whether the
808 * function is applied once atomically only if the value is not
809 * present. Any class that permits null values must document
810 * whether and how this method distinguishes absence from null
811 * mappings.
812 *
813 * @implSpec
814 * The default implementation is equivalent to the following
815 * steps for this {@code map}, then returning the current value or
816 * {@code null} if now absent:
817 *
818 * <pre> {@code
819 * if (map.get(key) == null) {
820 * V newValue = mappingFunction.apply(key);
821 * if (newValue != null)
822 * map.putIfAbsent(key, newValue);
823 * }}</pre>
824 *
825 * @param key key with which the specified value is to be associated
826 * @param mappingFunction the function to compute a value
827 * @return the current (existing or computed) value associated with
828 * the specified key, or null if the computed value is null
829 * @throws NullPointerException if the specified key is null and
830 * this map does not support null keys, or the
831 * mappingFunction is null
832 * @throws UnsupportedOperationException if the <tt>put</tt> operation
833 * is not supported by this map
834 * (<a href="Collection.html#optional-restrictions">optional</a>)
835 * @throws ClassCastException if the class of the specified key or value
836 * prevents it from being stored in this map
837 * (<a href="Collection.html#optional-restrictions">optional</a>)
838 * @since 1.8
839 */
840 default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
841 V v, newValue;
842 return ((v = get(key)) == null &&
843 (newValue = mappingFunction.apply(key)) != null &&
844 (v = putIfAbsent(key, newValue)) == null) ? newValue : v;
845 }
846
847 /**
848 * If the value for the specified key is present and non-null, attempts to
849 * compute a new mapping given the key and its current mapped value.
850 *
851 * <p>If the function returns {@code null}, the mapping is removed. If the
852 * function itself throws an (unchecked) exception, the exception is
853 * rethrown, and the current mapping is left unchanged.
854 *
855 * <p>The default implementation makes no guarantees about
856 * synchronization or atomicity properties of this method or the
857 * application of the remapping function. Any class overriding
858 * this method must specify its concurrency properties. In
859 * particular, all implementations of subinterface {@link
860 * java.util.concurrent.ConcurrentMap} must document whether the
861 * function is applied once atomically only if the value is
862 * present. Any class that permits null values must document
863 * whether and how this method distinguishes absence from null
864 * mappings.
865 *
866 * @implSpec
867 * The default implementation is equivalent to performing the
868 * following steps for this {@code map}, then returning the
869 * current value or {@code null} if now absent:
870 *
871 * <pre> {@code
872 * if (map.get(key) != null) {
873 * V oldValue = map.get(key);
874 * V newValue = remappingFunction.apply(key, oldValue);
875 * if (newValue != null)
876 * map.replace(key, oldValue, newValue);
877 * else
878 * map.remove(key, oldValue);
879 * }}</pre>
880 *
881 * In concurrent contexts, the default implementation may retry
882 * these steps when multiple threads attempt updates.
883 *
884 * @param key key with which the specified value is to be associated
885 * @param remappingFunction the function to compute a value
886 * @return the new value associated with the specified key, or null if none
887 * @throws NullPointerException if the specified key is null and
888 * this map does not support null keys, or the
889 * remappingFunction is null
890 * @throws UnsupportedOperationException if the <tt>put</tt> operation
891 * is not supported by this map
892 * (<a href="Collection.html#optional-restrictions">optional</a>)
893 * @throws ClassCastException if the class of the specified key or value
894 * prevents it from being stored in this map
895 * (<a href="Collection.html#optional-restrictions">optional</a>)
896 * @since 1.8
897 */
898 default V computeIfPresent(K key,
899 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
900 V oldValue;
901 while ((oldValue = get(key)) != null) {
902 V newValue = remappingFunction.apply(key, oldValue);
903 if (newValue != null) {
904 if (replace(key, oldValue, newValue))
905 return newValue;
906 } else if (remove(key, oldValue))
907 return null;
908 }
909 return oldValue;
910 }
911
912 /**
913 * Attempts to compute a mapping for the specified key and its
914 * current mapped value (or {@code null} if there is no current
915 * mapping). For example, to either create or append a {@code
916 * String msg} to a value mapping:
917 *
918 * <pre> {@code
919 * map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg))}</pre>
920 * (Method {@link #merge} is often simpler to use for such purposes.)
921 *
922 * <p>If the function returns {@code null}, the mapping is removed (or
923 * remains absent if initially absent). If the function itself throws an
924 * (unchecked) exception, the exception is rethrown, and the current mapping
925 * is left unchanged.
926 *
927 * <p>The default implementation makes no guarantees about
928 * synchronization or atomicity properties of this method or the
929 * application of the remapping function. Any class overriding
930 * this method must specify its concurrency properties. In
931 * particular, all implementations of subinterface {@link
932 * java.util.concurrent.ConcurrentMap} must document whether the
933 * function is applied exactly once atomically. Any class that
934 * permits null values must document whether and how this method
935 * distinguishes absence from null mappings.
936 *
937 * @implSpec
938 * The default implementation is equivalent to performing the following
939 * steps for this {@code map}, then returning the current value or
940 * {@code null} if absent:
941 *
942 * <pre>{@code
943 * V oldValue = map.get(key);
944 * V newValue = remappingFunction.apply(key, oldValue);
945 * if (oldValue != null )
946 * if (newValue != null)
947 * map.replace(key, oldValue, newValue);
948 * else
949 * map.remove(key, oldValue);
950 * else
951 * if (newValue != null)
952 * map.putIfAbsent(key, newValue);
953 * else
954 * return null;
955 * }</pre>
956 *
957 * In concurrent contexts, the default implementation may retry
958 * these steps when multiple threads attempt updates.
959 *
960 * @param key key with which the specified value is to be associated
961 * @param remappingFunction the function to compute a value
962 * @return the new value associated with the specified key, or null if none
963 * @throws NullPointerException if the specified key is null and
964 * this map does not support null keys, or the
965 * remappingFunction is null
966 * @throws UnsupportedOperationException if the <tt>put</tt> operation
967 * is not supported by this map
968 * (<a href="Collection.html#optional-restrictions">optional</a>)
969 * @throws ClassCastException if the class of the specified key or value
970 * prevents it from being stored in this map
971 * (<a href="Collection.html#optional-restrictions">optional</a>)
972 * @since 1.8
973 */
974 default V compute(K key,
975 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
976 V oldValue = get(key);
977 for (;;) {
978 V newValue = remappingFunction.apply(key, oldValue);
979 if (oldValue != null) {
980 if (newValue != null) {
981 if (replace(key, oldValue, newValue))
982 return newValue;
983 } else if (remove(key, oldValue)) {
984 return null;
985 }
986 oldValue = get(key);
987 } else {
988 if (newValue != null) {
989 if ((oldValue = putIfAbsent(key, newValue)) == null)
990 return newValue;
991 } else {
992 return null;
993 }
994 }
995 }
996 }
997
998 /**
999 * If the specified key is not already associated with a
1000 * (non-null) value, associates it with the given value.
1001 * Otherwise, replaces the value with the results of the given
1002 * remapping function, or removes if {@code null}. This method may
1003 * be of use when combining multiple mapped values for a key. For
1004 * example, to either create or append a {@code String msg} to a
1005 * value mapping:
1006 *
1007 * <pre> {@code
1008 * map.merge(key, msg, String::concat)}</pre>
1009 *
1010 * <p>If the function returns {@code null}, the mapping is removed (or
1011 * remains absent if initially absent). If the function itself throws an
1012 * (unchecked) exception, the exception is rethrown, and the current mapping
1013 * is left unchanged.
1014 *
1015 * <p>The default implementation makes no guarantees about
1016 * synchronization or atomicity properties of this method or the
1017 * application of the remapping function. Any class overriding
1018 * this method must specify its concurrency properties. In
1019 * particular, all implementations of subinterface {@link
1020 * java.util.concurrent.ConcurrentMap} must document whether the
1021 * function is applied exactly once atomically. Any class that
1022 * permits null values must document whether and how this method
1023 * distinguishes absence from null mappings.
1024 *
1025 * @implSpec
1026 * The default implementation is equivalent to performing the
1027 * following steps for this {@code map}, then returning the
1028 * current value or {@code null} if absent:
1029 *
1030 * <pre> {@code
1031 * V oldValue = map.get(key);
1032 * V newValue = (oldValue == null) ? value :
1033 * remappingFunction.apply(oldValue, value);
1034 * if (newValue == null)
1035 * map.remove(key, oldValue);
1036 * else if (oldValue == null)
1037 * map.putIfAbsent(key, newValue);
1038 * else
1039 * map.replace(key, oldValue, newValue);
1040 * }</pre>
1041 *
1042 * In concurrent contexts, the default implementation may retry
1043 * these steps when multiple threads attempt updates.
1044 *
1045 * @param key key with which the specified value is to be associated
1046 * @param value the value to use if absent
1047 * @param remappingFunction the function to recompute a value if present
1048 * @return the new value associated with the specified key, or null if none
1049 * @throws UnsupportedOperationException if the <tt>put</tt> operation
1050 * is not supported by this map
1051 * (<a href="Collection.html#optional-restrictions">optional</a>)
1052 * @throws ClassCastException if the class of the specified key or value
1053 * prevents it from being stored in this map
1054 * (<a href="Collection.html#optional-restrictions">optional</a>)
1055 * @throws NullPointerException if the specified key is null and
1056 * this map does not support null keys, or the
1057 * remappingFunction is null
1058 * @since 1.8
1059 */
1060 default V merge(K key, V value,
1061 BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
1062 V oldValue = get(key);
1063 for (;;) {
1064 if (oldValue != null) {
1065 V newValue = remappingFunction.apply(oldValue, value);
1066 if (newValue != null) {
1067 if (replace(key, oldValue, newValue))
1068 return newValue;
1069 } else if (remove(key, oldValue)) {
1070 return null;
1071 }
1072 oldValue = get(key);
1073 } else {
1074 if (value == null) {
1075 return null;
1076 }
1077
1078 if ((oldValue = putIfAbsent(key, value)) == null) {
1079 return value;
1080 }
1081 }
1082 }
1083 }
1084 }
|