Java ConcurrentMap Example

Even though Map is implemented by many classes, many of them are not thread-safe or some of them are but not efficient. This is why ConcurrentMap was introduced in Java 1.5. It is thread-safe and efficient.

Overridden default implementations:

  • compute
  • replaceAll
  • forEach
  • getOrDefault
  • computerIfAbsent
  • computerIfPresent

ConcurrentMap consists of an array of nodes that are represented as table buckets and they are initialised after the first insertion.

Efficiency comparison between ConcurrentMap and HashMap

  • If one wants to operate on data as fast as possible, all threads must be used, which therefore means that ConcurrentMap is more effective here.
  • If only a single thread access is required, HashMap is faster.
  • add method is 3 times faster if implemented by HashMap.
  • get method is faster if implemented by ConcurrentMap.

If a program requires multiple threads access, ConcurrentMap is the better option. However, if the program will only be using 1 thread, then HashMap would be the better option.



Methods in ConcurrentMap

  1. default V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction): Attempts to compute a mapping for the specified key and its current mapped value.
  2. default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction): If the key given as a parameter is not associated with a value (or null) , attempts to compute its value and enters it into this map unless null.
  3. default V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction): If the value for the specified key is present and non-null, attempts to compute a new mapping given the key and its current mapped value.
  4. default void forEach(BiConsumer<? super K, ? super V> action): performs the given action for each entry in the current map util all entries have been processed.
  5. default V getOrDefault(Object key, V defaultValue): returns the value which the specified key is mapped to or defaultValue (given as 2nd parameter) if the map contains no mapping for the key.
  6. default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction): if the key is not already associated with a value or is associated with null, then it associates it with the specified non-null value.
  7. V putIfAbsent(K key, V value): if the specified key has not been already associated with a value, associate it with the given value.
  8. boolean remove(Object key, Object value): removes the entry for a key only if currently mapped to a given value.
  9. V replace(K key, V value): replaces the entry for a key only if currently mapped to some value.
  10. boolean replace(K key, V oldValue, V newValue): replaces the entry for a key only if currently mapped to a given value.

For more information on the main methods of EnumSet, feel free to visit the original Oracle documentation.


Example program using some of the methods mentioned above

import java.util.concurrent.*; 
class ConcurrentHashMapExample { 
    public static void main(String[] args) 
        ConcurrentHashMap conCurrHashMap = new ConcurrentHashMap(); 
        conCurrHashMap.put(100, "Elephant"); 
        conCurrHashMap.put(101, "Tiger"); 
        conCurrHashMap.put(102, "Lion"); 
        conCurrHashMap.put(103, "Cow"); 
        // since 103 already exists, this won't work
        conCurrHashMap.putIfAbsent(103, "Goat"); 
        conCurrHashMap.remove(103, "Goat"); 
        System.out.println("After removal: " + conCurrHashMap);
        // since 103 was removed, this now works
        conCurrHashMap.putIfAbsent(103, "Leopard"); 
        System.out.println("After put: " + conCurrHashMap);
        // changing Goat to Cheetah
        conCurrHashMap.replace(103, "Leopard", "Cheetah"); 
        System.out.println("Final: " + conCurrHashMap); 



After removal: {100=Elephant, 101=Tiger, 102=Lion, 103=Cow}
After put: {100=Elephant, 101=Tiger, 102=Lion, 103=Cow}
Final: {100=Elephant, 101=Tiger, 102=Lion, 103=Cow}


Leave a Reply