counts.computeIfAbsent(key, k -> new LongAdder())
This entire expression can go one of two ways:
key is already in the
counts map. In this case, the 'computer' function (
k -> new LongAdder()) is completely ignored; it isn't run at all. Instead, the value associated with that key is returned.
key is not in the
counts map. In this case, the 'computer' function is executed once, and the value it returns is now associated with the key.
In other words, it's identical to:
if (counts.containsKey(key)) result = counts.get(key);
result = new LongAdder();
Which is a mouthful, potentially less efficient, and potentially non-atomic whereas
.computerIfAbsent can be atomic if you use the right implementation (such as
Here's the clue: You then invoke
.increment() on this result, regardless of whether we're in the #1 case or the #2 case.
In other words:
First 'row' is seen,
computeIfAbsent ends up executing the lambda and thus, runs something like
counts.put(k, new LongAdder()) and THEN you call
.increment() on this.
Next, the second 'row' is seen,
computeIfAbsent ends up being equivalent to
counts.get(key), and you call
.increment() on that. Which is the same LongAdder we made when we saw the first 'row', and thus this is the second time you are invoking
increment() on it.
computeIfAbsent that's incrementing anything. It's the
.increment() that increments something.