通过 Stream API 有条件地将 Java 对象列表合并到地图中

Conditionally merging list of Java objects into a map via Stream API

Java 11 在这里。我有一个 List<Foobar> 和一个 Map<Foobar,List<String>>.

我想遍历列表并且:

我可以这样完成:

List<Foobar> foobarList = getSomehow();
Map<Foobar,List<String>> foobarMap = getItSomehow();
String msg = "Can't please everyone";
for (Foobar fb : foobarList) {
    if (foobarMap.containsKey(fb)) {
        foobarMap.get(fb).add(msg);
    } else {
        foobarMap.put(fb, Collections.singletonList(msg));
    }
}

这很好用,但我正在尝试使用 Java 流 API 让它工作。迄今为止我的最佳尝试:

List<Foobar> foobarList = getSomehow();
Map<Foobar,List<String>> foobarMap = getItSomehow();
String msg = "Can't please everyone";
foobarList.stream()
    .filter(fb -> foobarMap.containsKey(fb))
        .map(fb -> foobarMap.get(fb).add(msg))
    .filter(fb -> !foobarMap.containsKey(fb))
        .map(fb -> foobarMap.put(fb. Collections.singleton(msg));

产生几个编译器错误。谁能发现我哪里出错了?

流被使用

  • 要修改流元素的内容,或者
  • 从中生成另一个流,或者
  • 遍历元素并做一些不影响 this 流的元素的事情。

由于你的用例是最后一个类型,所以逻辑操作很简单forEach(..)。 (我知道这是一个阻尼器 :-),但这就是用例。)

foobarList.forEach( fb -> {
    if (foobarMap.containsKey(fb)) {
        foobarMap.get(fb).add(msg);
    } else {
         foobarMap.put(fb, Collections.singletonList(msg));
    }
} );

正如@Sree Kumar 所注意到的,您应该使用 forEach()

但是,我建议利用 Map.merge() 方法:

foobarList.forEach(fb -> foobarMap.merge(fb, Collections.singletonList(msg),
        (l1, l2) -> Stream.concat(l1.stream(), l2.stream()).toList()));