通过 Stream API 有条件地将 Java 对象列表合并到地图中
Conditionally merging list of Java objects into a map via Stream API
Java 11 在这里。我有一个 List<Foobar>
和一个 Map<Foobar,List<String>>
.
我想遍历列表并且:
- 如果当前
Foobar
是映射中的键,并且特定字符串(“不能取悦所有人”)到该条目的值列表
- 如果当前
Foobar
不是映射中的键,并且它是一个新键,其值是 ArrayList
由具有相同值的单个字符串组成
我可以这样完成:
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()));
Java 11 在这里。我有一个 List<Foobar>
和一个 Map<Foobar,List<String>>
.
我想遍历列表并且:
- 如果当前
Foobar
是映射中的键,并且特定字符串(“不能取悦所有人”)到该条目的值列表 - 如果当前
Foobar
不是映射中的键,并且它是一个新键,其值是ArrayList
由具有相同值的单个字符串组成
我可以这样完成:
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()));