在Java 8中,有没有更简洁的方法可以做到这一点-地图操作

时间:2019-07-09 10:02:21

标签: java lambda collections

在集合地图上的一个非常常见的操作是在不存在键的情况下创建一个具有初始值的新集合,或者如果存在键,则对现有集合执行某些功能。以一个Map<String, Set<Integer>>为例,如果键不存在,则创建一个初始值为1的Set。如果键在那里,则将值map.size()+ 1添加到该集中(或替换为该值)功能以及其他一些简单的单线操作)。在Java 7中,使用if / else很简单,但是很冗长。我只能针对Java 8提出以下代码,但它并没有好得多(由于代码行多,所以实际上会更糟)。有没有办法使它更简洁?

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

2 个答案:

答案 0 :(得分:3)

不幸的是,它不是单线的,但它发挥了魔力,并且也更易于阅读(缺点:每次都会创建一个新的HashSet<>()

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

或由@Thilo提出并受@Eran启发

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

一个内衬是可能的,因为它返回了javadoc

中提到的计算得出的值
  

如果指定的键尚未与某个值关联(或已映射为null),则尝试使用给定的映射函数计算其值,除非为null,否则将其输入到此映射中。

javadoc

中甚至有一个类似的例子
  

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

衬里的一点取舍是对m.get(key)的额外调用,而@Eran的解决方案却没有发生

答案 1 :(得分:3)

这是另一种选择:

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

这是两个衬里(而不是一个衬里)的唯一原因是需要确定Set的当前大小,以便确定要添加哪个值。