是否可以在单个语句中使用filter(),collect()和foreach()而不是多个语句?
我有一张地图,需要根据某些条件进行过滤,并为内容设置一些值并返回地图。我的当前看起来如下,但我希望所有3个单一陈述。
映射inputMap(包含所有信息)
Map<String, Person> returnMap;
returnMap = map.entrySet().stream()
.filter(p -> p.getValue().getCourse() == 123)
.collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));
returnMap.entrySet().stream().forEach((entry) -> {
Person person= entry.getValue();
person.setAction("update");
person.setLastUpdatedTime(new Date());
});
可以转换为,
Map<String, Person> returnMap;
returnMap = map.entrySet().stream()
.filter(p -> p.getValue().getCourse() == 123)
.collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()))
.forEach((entry) -> {
Person person= entry.getValue();
person.setAction("update");
person.setLastUpdatedTime(new Date());
});
(此代码不起作用)
答案 0 :(得分:14)
问题是forEach
没有返回一个对象,所以你必须处理不同的对象。你可以这样做:
Map<String, Person> returnMap = new HashMap<>();
map.entrySet().stream()
.filter(p -> p.getValue().getCourse() == 123)
.forEach((entry) -> {
Person person = entry.getValue();
person.setAction("update");
person.setLastUpdatedTime(new Date());
returnMap.put(entry.getKey(), person);
});
答案 1 :(得分:2)
坚持用一次手术做这件事没有任何意义。无论你如何写下来,这些都是两个操作。
但是你要考虑的一件事是,除entrySet().stream()
之外还有更多的方法来处理所有元素:
Map<String, Person> returnMap = map.entrySet().stream()
.filter(p -> p.getValue().getCourse() == 123)
.collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));
returnMap.values().forEach(person -> {
person.setAction("update");
person.setLastUpdatedTime(new Date());
});
如果你仍然坚持让它看起来像一个单一的操作,你可以这样做:
Map<String, Person> returnMap = map.entrySet().stream()
.filter(p -> p.getValue().getCourse() == 123)
.collect(Collectors.collectingAndThen(
Collectors.toMap(p -> p.getKey(), p -> p.getValue()),
tmp -> {
tmp.values().forEach(person -> {
person.setAction("update");
person.setLastUpdatedTime(new Date());
});
return tmp;
})
);
这在语法上是单个语句,但它与前一个变体完全相同。
答案 2 :(得分:0)
我不明白是否需要按照建议将其分为两个步骤。似乎转换可以在终端操作之前完成,如下所示:
returnMap = map.entrySet().stream()
.filter(p -> p.getValue().getCourse() == 123)
.map(e -> {
Person p = e.getValue();
p.setAction("update");
p.setLastUpdatedTime(new Date());
return e;
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
如果您对正在流式传输的Map.Entry
产生副作用,那么您可以返回一个新的AbstractMap.SimpleEntry
,其中包含更新的Person
作为其值,但到目前为止还没有一个解决方案没有副作用,因为原始地图中的值正在被修改。无论如何,这是变化:
returnMap = map.entrySet().stream()
.filter(p -> p.getValue().getCourse() == 123)
.map(e -> {
Person p = e.getValue();
p.setAction("update");
p.setLastUpdatedTime(new Date());
return new AbstractMap.SimpleEntry<>(e.getKey(), p);
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));