1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * Written by Doug Lea with assistance from members of JCP JSR-166
  32  * Expert Group and released to the public domain, as explained at
  33  * http://creativecommons.org/publicdomain/zero/1.0/
  34  */
  35 
  36 package java.util.concurrent;
  37 import java.util.Map;
  38 import java.util.Objects;
  39 import java.util.function.BiFunction;
  40 
  41 /**
  42  * A {@link java.util.Map} providing thread safety and atomicity
  43  * guarantees.
  44  *
  45  * <p>Memory consistency effects: As with other concurrent
  46  * collections, actions in a thread prior to placing an object into a
  47  * {@code ConcurrentMap} as a key or value
  48  * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
  49  * actions subsequent to the access or removal of that object from
  50  * the {@code ConcurrentMap} in another thread.
  51  *
  52  * <p>This interface is a member of the
  53  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  54  * Java Collections Framework</a>.
  55  *
  56  * @since 1.5
  57  * @author Doug Lea
  58  * @param <K> the type of keys maintained by this map
  59  * @param <V> the type of mapped values
  60  */
  61 public interface ConcurrentMap<K, V> extends Map<K, V> {
  62 
  63     /**
  64      * {@inheritDoc}
  65      *
  66      * @implNote This implementation assumes that the ConcurrentMap cannot
  67      * contain null values and get() returning null unambiguously means the key
  68      * is absent. Implementations which support null values must override this
  69      * default implementation.
  70      */
  71     @Override
  72     default V getOrDefault(Object key, V defaultValue) {
  73         V v;
  74         return ((v = get(key)) != null) ? v : defaultValue;
  75     }
  76 
  77     /**
  78      * If the specified key is not already associated
  79      * with a value, associate it with the given value.
  80      * This is equivalent to
  81      *  <pre> {@code
  82      * if (!map.containsKey(key))
  83      *   return map.put(key, value);
  84      * else
  85      *   return map.get(key);}</pre>
  86      *
  87      * except that the action is performed atomically.
  88      *
  89      * @param key key with which the specified value is to be associated
  90      * @param value value to be associated with the specified key
  91      * @return the previous value associated with the specified key, or
  92      *         {@code null} if there was no mapping for the key.
  93      *         (A {@code null} return can also indicate that the map
  94      *         previously associated {@code null} with the key,
  95      *         if the implementation supports null values.)
  96      * @throws UnsupportedOperationException if the {@code put} operation
  97      *         is not supported by this map
  98      * @throws ClassCastException if the class of the specified key or value
  99      *         prevents it from being stored in this map
 100      * @throws NullPointerException if the specified key or value is null,
 101      *         and this map does not permit null keys or values
 102      * @throws IllegalArgumentException if some property of the specified key
 103      *         or value prevents it from being stored in this map
 104      */
 105     V putIfAbsent(K key, V value);
 106 
 107     /**
 108      * Removes the entry for a key only if currently mapped to a given value.
 109      * This is equivalent to
 110      *  <pre> {@code
 111      * if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
 112      *   map.remove(key);
 113      *   return true;
 114      * } else
 115      *   return false;}</pre>
 116      *
 117      * except that the action is performed atomically.
 118      *
 119      * @param key key with which the specified value is associated
 120      * @param value value expected to be associated with the specified key
 121      * @return {@code true} if the value was removed
 122      * @throws UnsupportedOperationException if the {@code remove} operation
 123      *         is not supported by this map
 124      * @throws ClassCastException if the key or value is of an inappropriate
 125      *         type for this map
 126      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
 127      * @throws NullPointerException if the specified key or value is null,
 128      *         and this map does not permit null keys or values
 129      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
 130      */
 131     boolean remove(Object key, Object value);
 132 
 133     /**
 134      * Replaces the entry for a key only if currently mapped to a given value.
 135      * This is equivalent to
 136      *  <pre> {@code
 137      * if (map.containsKey(key) && Objects.equals(map.get(key), oldValue)) {
 138      *   map.put(key, newValue);
 139      *   return true;
 140      * } else
 141      *   return false;}</pre>
 142      *
 143      * except that the action is performed atomically.
 144      *
 145      * @param key key with which the specified value is associated
 146      * @param oldValue value expected to be associated with the specified key
 147      * @param newValue value to be associated with the specified key
 148      * @return {@code true} if the value was replaced
 149      * @throws UnsupportedOperationException if the {@code put} operation
 150      *         is not supported by this map
 151      * @throws ClassCastException if the class of a specified key or value
 152      *         prevents it from being stored in this map
 153      * @throws NullPointerException if a specified key or value is null,
 154      *         and this map does not permit null keys or values
 155      * @throws IllegalArgumentException if some property of a specified key
 156      *         or value prevents it from being stored in this map
 157      */
 158     boolean replace(K key, V oldValue, V newValue);
 159 
 160     /**
 161      * Replaces the entry for a key only if currently mapped to some value.
 162      * This is equivalent to
 163      *  <pre> {@code
 164      * if (map.containsKey(key)) {
 165      *   return map.put(key, value);
 166      * } else
 167      *   return null;}</pre>
 168      *
 169      * except that the action is performed atomically.
 170      *
 171      * @param key key with which the specified value is associated
 172      * @param value value to be associated with the specified key
 173      * @return the previous value associated with the specified key, or
 174      *         {@code null} if there was no mapping for the key.
 175      *         (A {@code null} return can also indicate that the map
 176      *         previously associated {@code null} with the key,
 177      *         if the implementation supports null values.)
 178      * @throws UnsupportedOperationException if the {@code put} operation
 179      *         is not supported by this map
 180      * @throws ClassCastException if the class of the specified key or value
 181      *         prevents it from being stored in this map
 182      * @throws NullPointerException if the specified key or value is null,
 183      *         and this map does not permit null keys or values
 184      * @throws IllegalArgumentException if some property of the specified key
 185      *         or value prevents it from being stored in this map
 186      */
 187     V replace(K key, V value);
 188 
 189     /**
 190      * {@inheritDoc}
 191      *
 192      * @implNote This implementation assumes that the ConcurrentMap cannot
 193      * contain null values and get() returning null unambiguously means the key
 194      * is absent. Implementations which support null values
 195      * <strong>must</strong> override this default implementation.
 196      */
 197     @Override
 198     default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
 199         Objects.requireNonNull(function);
 200         forEach((k,v) -> {
 201             while(!replace(k, v, function.apply(k, v))) {
 202                 // v changed or k is gone
 203                 if( (v = get(k)) == null) {
 204                     // k is no longer in the map.
 205                     break;
 206                 }
 207             }
 208         });
 209     }
 210 }