Java8 introduced those nice methods getOrDefault()
and putIfAbsent()
, allowing to write code like:
Map>
An important point about computeIfAbsent
is that it takes a Function
which will only get executed if the Key
is absent and we need a default Value
.
Whereas getOrDefault
requires the default Value
itself, already computed. In this case, the default Value
we would need is a new ArrayList<Bar>()
, which has the side effect of allocating a new object on the heap.
We want to defer doing that until we are sure that the key
isn't already in itemsByFoo
. Otherwise we would be generating unnecessary garbage for gc
to collect.
getOrDefault
is suitable if you want to use a stand-in for an absent value without modifying the map. If you want to add a new value for absent keys, you can do it right in one operation.
List<Bar> bars = itemsByFoo.computeIfAbsent(key, x -> new ArrayList<>());
bars.add(someNewBar);
or even
itemsByFoo.computeIfAbsent(key, x -> new ArrayList<>()).add(someNewBar);
In the best case, when being overridden by the Map
implementation, like with HashMap
, this will bear a single hash lookup only.
Not that putIfAbsent
only bears two lookups when using the default
implementation, but, of course, most Map
implementations will provide a single lookup implementation for it. Still, the combination of getOrDefault
and putIfAbsent
would still bear two lookups in the best case, whereas an optimized computeIfAbsent
does only one.