1. Overview
In this tutorial, we’ll discuss the new default method, computeIfAbsent, of the Map interface introduced in Java 8.
Specifically, we’ll look at its signature, usage, and how it handles different cases.
2. Map.computeIfAbsent Method
Let’s start by looking at the signature of computeIfAbsent:
default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
The computeIfAbsent method takes two parameters. The first parameter is the key, and the second parameter is the mappingFunction. It’s important to know that the mapping function is only called if the mapping isn’t present.
2.1. Key Related to a Non-Null Value
First, it checks if the key is present in the map. If the key is present, and a non-null value is related to the key, then it returns that value:
Map<String, Integer> stringLength = new HashMap<>();
stringLength.put("John", 5);
assertEquals((long)stringLength.computeIfAbsent("John", s -> s.length()), 5);
As we can see, the key “John” has a non-null mapping present, and it returns the value 5. If our mapping function was used, we’d expect the function to return the length of 4.
2.2. Using the Mapping Function to Compute the Value
Furthermore, if the key isn’t present in the map, or the null value is related to the key, then it attempts to compute the value using the given mappingFunction. It also enters the calculated value into the map unless the calculated value is null.
Let’s take a look at the use of the mappingFunction in the computeIfAbsent method:
Map<String, Integer> stringLength = new HashMap<>();
assertEquals((long)stringLength.computeIfAbsent("John", s -> s.length()), 4);
assertEquals((long)stringLength.get("John"), 4);
Since the key “John” isn’t present, it computes the value by passing the key as a parameter to the mappingFunction.
2.3. Mapping Function Returns null
Also, if the mappingFunction returns null, the map records no mapping:
Map<String, Integer> stringLength = new HashMap<>();
assertEquals(stringLength.computeIfAbsent("John", s -> null), null);
assertNull(stringLength.get("John"));
2.4. Mapping Function Throws an Exception
Finally, if the mappingFunction throws an unchecked exception, then the exception is re-thrown, and the map records no mapping:
@Test(expected = RuntimeException.class)
public void whenMappingFunctionThrowsException_thenExceptionIsRethrown() {
Map<String, Integer> stringLength = new HashMap<>();
stringLength.computeIfAbsent("John", s -> { throw new RuntimeException(); });
}
We can see that the mappingFunction throws a RuntimeException, which propagates back to the computeIfAbsent method.
3. Conclusion
In this brief article, we focused on the computeIfAbsent method, its signature, and its usage. Finally, we learned how it handles different cases.
As always, all of these code samples are available over on GitHub.