Java8 Stream - 使用过滤器以单行收集foreach

sku*_*mar 7 java-8 java-stream

是不是可以在单个语句中使用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());
            });
Run Code Online (Sandbox Code Playgroud)

这可以转换成,

  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());
                });
Run Code Online (Sandbox Code Playgroud)

(此代码不起作用)

Kev*_*lis 16

问题是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);
                });
Run Code Online (Sandbox Code Playgroud)


Hol*_*ger 8

坚持一次操作是没有意义的。不管你怎么写,这都是两个操作。

但是您应该考虑的一件事是,除了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());
});
Run Code Online (Sandbox Code Playgroud)

如果你仍然坚持让它看起来像一个单一的操作,你可以这样做:

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;
        })
    );
Run Code Online (Sandbox Code Playgroud)

这在语法上是一个单一的语句,但它的作用与前一个变体完全相同。