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

岁酱吖の 提交于 2020-01-11 10:07:51

问题


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;
        }
    });
}

回答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.




回答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



来源:https://stackoverflow.com/questions/56950105/is-there-a-more-concise-way-to-do-this-in-java-8-map-manipulation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!