Java Map computeIfAbsent()

The Map.computeIfAbsent() method computes the mapped value for a key using a mapping function if the specified key does not exist in the Map or is mapped to a null value. It has been added as the default method in the Map interface in Java 8.

1. When to Use the computeIfAbsent() Method?

1.1. When Mapper Function is an Expensive Operation

The Map.computeIfAbsent() should be used when computing the value is a “costly operation”. For example, if a Map stores a number as key and its factorial as value then we can use the computeIfAbsent() as computing factorial is a memory-intensive operation.

Map<Integer, BigInteger> map = new HashMap<>();

map.computeIfAbsent(5, Main::factorial);
map.computeIfAbsent(6, Main::factorial);

//Inserting in another place
map.computeIfAbsent(6, Main::factorial);  //Factorial is not calculated here


static BigInteger factorial(Integer num) {

  System.out.println("Calculating the factorial of : " + num);
  return BigIntegerMath.factorial(num);
}

The program outputs the print statements only two times. In the third time, as the key already exists in the Map, the mapper function is not invoked and the factorial is not calculated.

Calculating the factorial of : 5
Calculating the factorial of : 6

1.2. Creating Multi Map

Another common use of computeIfAbsent() is to create a multi-valued map. A multi-value map maps a single key with multiple values, generally in a List.

In the following example, the first invocation with “State1” will result in creating a new List, mapping it to the key and adding “City1” to it. On the second invocation, since the key “State1” is already present, a new List will not be created and “City2” would be added to the existing list.

Map<String, List<String>> multiMap = new HashMap<>();

multiMap.computeIfAbsent("State1", k -> new ArrayList<>()).add("City1");
multiMap.computeIfAbsent("State1", k -> new ArrayList<>()).add("City2");

System.out.println(multiMap); //{State1=[City1, City2]}

2. Map.computeIfAbsent() Syntax

The method syntax is:

default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)

Parameters

The computeIfAbsent() takes two parameters:

  • key: the key for the mapping to be stored.
  • mappingFunction: non-null mapping function would only be invoked if the given key is not mapped to any value. It computes the new value for the specified key.

Return Value

The computeIfAbsent() returns the current value (either new or old) associated with the key after computation. It can return null if no value is associated with the key.

If mappingFunction results null, then the mapping for the specified key is removed.

3. How to Use Mapper Function?

Let us see a few examples to understand the method usage better.

3.1. Mapper Function should not be NULL

The mapping function has to be non-null else a NullPointerException is thrown. In the following code, we are passing null as the mapper function, so it will throw the NullPointerException.

Map<Integer, BigInteger> map = new HashMap<>();

map.computeIfAbsent(6, null);

3.2. Mapper Function is allowed to return NULL

There may be cases where the mapping function returns null values. In such a scenario, an entry is not created in the Map but the operation does not throw any exception.

Map<Integer, BigInteger> map = new HashMap<>();

map.computeIfAbsent(7, k -> null);   //No entry is created in the map

assertNull( map.get(7) );

3.3. Mapper Function throwing an unchecked exception

In case the mapping function throws an unchecked exception, the exception is re-thrown and no entry is created in the map.

In the following code, an exception has been thrown from the mapper function when we try to add key 7. In the catch block, we are confirming that they entry was not created in the Map.

try {
	map.computeIfAbsent(7, k-> {
		throw new RuntimeException();
	});
} catch (Exception e) {
	assertNull( map.get(7) );
}

4. Difference with compute() and computeIfPresent()

Map interface has 3 compute methods.

  • compute()
  • computeIfPresent()
  • computeIfAbsent()

These functions look the same but they are not. The compute() and computeIfPresent() uses the BiFunction as remapper function. It takes the specified key and currently mapped value as method arguments and attempts to compute a new mapping.

The compute() invokes the mapping function always, whereas computeIfPresent() invokes the mapper function only when the value is present for the specified key, and it is non-null.

Map<Integer, BigInteger> map = new HashMap<>();
map.put(1, null);

map.computeIfPresent(1, (k, v) -> Main.factorial(k)); //factorial is not executed

map.compute(1, (k, v) -> Main.factorial(k));  //factorial is executed

5. Conclusion

In this article, we looked at the Java 8 Map.computeIfAbsent() method. We learned when to use this method and how to handle NULL values and exceptions. We also compared it with compute() and computeIfPresent() methods.

Happy Learning !!

Source Code on Github

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode