1. Overview
In this tutorial, we'll look briefly at the new default method computeIfAbsent of the Map interface introduced in Java 8.
Specifically, we will 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 mapping function is only called if the mapping is not present.
2.1. Key Related to a Non-Null Value
Firstly, 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 see, the key “John” has a non-null mapping present, it returns the value 5. If our mapping function were 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 is not present in the map or null value is related to the key, then it attempts to compute the value using the given mappingFunction. Also, it enters the calculated value into the map unless the calculated value is null.
Let's take a look at the usage 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” is not 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 see that the mappingFunction throws a RuntimeException, which propagates back to the computeIfAbsent method.
3. Conclusion
In this quick article, we looked at the computeIfAbsent method, its signature and its usage. Finally, we saw how it handles different cases.
As always, all these code samples are available over on GitHub.