Java HashMap computeIfAbsent() - How to Use?

Backend Pro
In this article, we look at the ins and outs of Java HashMap computeIfAbsent() from Java 8.

Overview 

The computeIfAbsent method is introduced to the HashMap data structure from Java 8 version. 

The syntax of this method is as follows 

    public V computeIfAbsent(K key, Function mappingFunction) 
   
  • Here key represents the key in the Hash map. 
  • mappingFunction is a function that computes the value. Remember that the mapping function is only called when the value mapped to the key does not exist or it is null.

How does computeIfAbsent() work?

  • If the given key is not already mapped to a value (or is mapped to null), the mappingFunction is invoked to compute the value and enters into the map if it is not null. 
  • If the mappingFunction returns null, the map will not be updated. 
  • If the mappingFunction throws a runtime exception, the exception is rethrown, and this map will not be updated for the provided key.
  • The mappingFunction should not modify this map during computation. 
  • Throws ConcurrentModifiedException if it is detected that the mapping function modified this map.

When should we use computeIfAbsent()?

  • Most common usage is to insert a key/value pair into the hashmap where the value is always a new object initially.

    ex: instead of 
  • 
    Map<String, Foo> fooMap = new HashMap<>();
    if(fooMap.get("foo") == null) {
            fooMap.put("foo", new Foo());
    } else {
            // update foo
    }
    

we can use computeIfAbsent() as below and avoid the if/else checks.

  Map<String, Foo> fooMap = new
    HashMap<>();fooMap.computeIfAbsent("foo",  k -> new Foo());
    // update foo
    
  • To implement a multi-value map, Map<K, Collection<V>> i.e having multiple values per key. 

  • ex: Instead of 
    
        Map<String, List<Foo>> fooListMap = new HashMap<>();
        if(fooListMap.get("foo") == null) {
            fooListMap.put("foo", new ArrayList<Foo>());
        } 
        fooListMap.get("foo").add(new Foo());
we can use computeIfAbsent() as below and write in a single statement.

Map<String, List<Foo>> fooListMap = new HashMap<>();
fooListMap.computeIfAbsent("foo", k -> new ArrayList<Foo>()).add(new Foo());
    

Further examples

Using computeIfAbsent() when the value is null

When the key is not mapped to a value or the mapped value is null, then the computeIfAbsent() method invokes the mapping function to derive the value. Remember, if the mapping function returns a null, then the map will not be updated.

  Map stringMap = new HashMap<>();
  System.out.println(stringMap.get("TheBackendPro")); // prints null
  stringMap.computeIfAbsent("TheBackendPro", k -> {
     return "https://www.thebackendpro.com/";
  });

  System.out.println(stringMap.get("TheBackendPro")); // prints https://www.thebackendpro.com/
  

Using computeIfAbsent() when the key is already mapped to a non-null value

If the key is already associated with a non-null value, the computeIfAbsent() doesn't invoke the mapping function as the value is already present.

  Map stringMap = new HashMap<>();
  stringMap.put("TheBackendPro", "https://www.thebackendpro.com/");
  stringMap.computeIfAbsent("TheBackendPro", k -> {
     return "https://www.google.com/";
  });
  System.out.println(stringMap.get("TheBackendPro")); // prints https://www.thebackendpro.com/
  

Mapping Function Throws a Runtime Exception

When the mapping function throws a runtime exception, the same is propagated to the caller and no mapping is recorded for the key.

  Map stringMap = new HashMap<>();
  stringMap.computeIfAbsent("TheBackendPro", k -> {
     throw new RuntimeException("unexpected exception occurred");
  });
  

Output


  Exception in thread "main" java.lang.RuntimeException: unexpected exception occurred
	at main.java.ComputeIfAbsentTest.lambda$main$2(ComputeIfAbsentTest.java:26)
	at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1134)
	at main.java.ComputeIfAbsentTest.main(ComputeIfAbsentTest.java:25)
  
Tags

#buttons=(Accept !) #days=(20)

Our website uses cookies to enhance your experience. Check Now
Accept !