Search code examples
javacollectionssynchronizedjava.util.concurrentconcurrenthashmap

How to implement atomic getOrDefaultWithPut() based on getOrDefault() in ConcurrentHashMap?


ConcurrentHashMap supports atomic getOrDefault(Object key, V defaultValue), which

Returns the value to which the specified key is mapped, or the given default value if this map contains no mapping for the key.

My problem is:

How can I enhance ConcurrentHashMap by providing an atomic operation, say getOrDefaultWithPut(Object key, V defaultValue), which

"Returns the value to which the specified key is mapped, or first put the the given default value into the map and then return the default value if this map contains no mapping for the key.`"


My solution:

Currently I have a Wrapper class of

 private ConcurrentMap<K, V> map = new ConcurrentHashMap<>();

The method is:

public synchronized K getOrDefaultWithPut(K key, V defaultValue)
{
    map.putIfAbsent(key, defaultValue);
    return map.get(key);
}
  1. Is this implementation thread-safe?
  2. Is synchronized necessary? What bad would happen if it is removed?
  3. If getOrDefaultWithPut(K key, V defaultValue) is the only public method of Wrapper, is this implementation thread-safe and is synchronized necessary?

Solution

  • Just use computeIfAbsent

    If the specified key is not already associated with a value, attempts to compute its value using the given mapping function and enters it into this map unless null. The entire method invocation is performed atomically [...]

    Returns

    the current (existing or computed) value associated with the specified key, or null if the computed value is null

    Provide a mappingFunction which generates your default value and this will satisfy your requirement.

    Returns the value to which the specified key is mapped

    That's the existing value.

    or first put the the given default value into the map and then return the default value if this map contains no mapping for the key

    The method will insert the computed value (the default), if not null, and return that computed value.


    You won't need synchronized with this solution. The method invocation is atomic and it's therefore thread safe.