[concurrency-interest] ConcurrentMap.replace

Doug Lea dl@cs.oswego.edu
Sat, 22 Nov 2003 07:39:45 -0500

Eric and others,

I think the functionality you are getting at can be addressed by:

  public interface ConcurrentMap<K, V> extends Map<K, V> {
      // ...

       * Replace entry for key only if currently mapped to given value.
       * Acts as
       * <pre> 
       *  if (map.containsKey(key) && map.get(key).equals(oldValue)) {
       *     map.put(key, newValue);
       *     return true;
       * } else return false;
       * </pre>
       * except that the action is performed atomically.
       * @param key key with which the specified value is associated.
       * @param oldValue value expected to be associated with the specified key.
       * @param newValue value to be associated with the specified key.
       * @return true if the value was replaced
       * @throws NullPointerException if this map does not permit <tt>null</tt>
       *            keys or values, and the specified key or value is
       *            <tt>null</tt>.
      boolean replace(K key, V oldValue, V newValue);

The fact that this can be specified in almost exactly the same way as
ConcurrentMap.remove(key, value) bolsters confidence that it fills a
gap we had left in this API.  (Note also the similarity to
compareAndSet in the atomic classes.)

I think it can be used to cover the use cases people have sent for


It is getting to be late for adding things like this, but ought to
be possible.

It's too bad that replace(key, null, value) cannot mean
putIfAbsent(key, value), in which case we could do away with
putIfAbsent.  But to mesh with java.util interface conventions, we
cannot preclude null being a legal mapping in some Map
implementations. Null is not a legal mapping value for
ConcurrentHashMap, but the ConcurrentMap interface is designed to be
implementable by future concurrent map implementations (probably
including a sorted map of some kind) in future releases, that might
wish to allow null values. (Further digressing: I personally think
that allowing null value mappings is a travesty. Use the NullObject
pattern instead!  see http://c2.com/cgi/wiki?NullObject).