'Is there a more concise way to do this in Java 8 - Map manipulation

A very common operation on maps of collections is to create a new collection with an initial value when the key is not present, or if the key is present, do some function on the existing collection. Take for example a Map<String, Set<Integer>>, if the key is not there, create a Set with an initial value of 1. If the key is there, add the value map.size()+1 to the set (or replace this function with some other simple one-liner operation). In Java 7, it's straightforward with if/else, but pretty verbose. I can only come up with the below code for Java 8, which isn't much better (actually worse due to more lines of code). Is there a way to make this more concise?

public void process(Map<String, Set<Integer>> m, String key) {
    m.compute(key, (k, v) -> {
        if (v == null) {
            v = new HashSet<>();
            v.add(1);
            return v;
        } else {
            v.add(v.size() + 1);
            return v;
        }
    });
}


Solution 1:[1]

Here's another alternative:

Set<Integer> set = m.computeIfAbsent (key , k -> new HashSet<> ());
set.add(set.size() + 1);

The only reason this is a two liner (instead of one) is the need to obtain the current size of the Set in order to decide which value to add to it.

Solution 2:[2]

Not a one-liner unfortunately but it does its magic and is also directly more readable (downside : it creates a new HashSet<>() everytime)

m.putIfAbsent(key, new HashSet<>());
// Solution 1 :
m.compute(key, (k, v) -> {v.add(v.size() + 1); return v;});
// Solution 2 :
Set<Integer> s = m.get(key);
s.add(s.size() + 1);

Or as proposed by @Thilo and inspired by @Eran

m.computeIfAbsent(key, k -> new HashSet<>()).add(m.get(key).size() + 1);

The one liner is possible because it returns the value it computed as mentioned in the javadoc

If the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null.

There is even a similar example in the javadoc

map.computeIfAbsent(key, k -> new HashSet()).add(v);

The little trade-off of the liner is the extra call to m.get(key) which is not happening with the solution of @Eran

Solution 3:[3]

Set<Integer> v = m.getOrDefault(key, new HashSet<>());
v.add(v.size() + 1);
m.put(key, v);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 vince