Java 8流如果不执行收集函数,则过滤和映射函数不起作用


public static void main(String[] args) throws Exception {
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
// below code does not work
list.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
System.out.println("1:test:" + s);
return true;
}
}).map(s -> {
System.out.println("1:map:" + s);
return s;
});

// below code works
list.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
System.out.println("2:test" + s);
return true;
}
}).map(s -> {
System.out.println("2:map" + s);
return s;
}).collect(Collectors.toList());
}

上述代码的输出为:

2:test1
2:map1
2:test2
2:map2
2:test3
2:map3
2:test4
2:map4

我不知道为什么第一次不起作用。

只有在执行lambda时才会调用lambdap -> doSomething(p)中的doSomething。该语句的简单存在并不保证执行,而普通(而不是lambda(语句doSomething(x)保证执行。

mapfilter是中间操作,而collect是终端操作。对于每一个中间操作,都会返回一个新的流对象(Stream的任何实现,如StatelessOpStatefulOp或流的基元专用化(如IntStreamLongStream等((,它存储任何信息,如您的情况下的映射或过滤函数。这里没有实际执行。

流评估是在调用evaluate方法时进行的。现在,如果您看到任何终端操作,它都会调用这个evaluate方法。这是您作为参数传递给中间操作的lambda应用于流元素的情况。这就是为什么流被认为是惰性评估的原因->评估仅从应用终端操作开始。

因此,您的第一个代码块不起作用,因为没有终端操作,并且您传递的lambda也没有执行。但在第二个代码块中,您调用了一个终端操作,并对流进行了评估。还要注意,不需要针对每个流元素执行中间操作->参考

您可以在ReferencePipeline中看到每个流方法的实现。

流管道由一个源(可能是一个数组集合、生成器函数、I/O通道等(,零或更多中间操作(将一个流转换为另一个流,例如filter(Predicate((和终端操作(产生结果或副作用,如count((或forEach(Consumer((。流懒惰;只有当终端操作启动,并且仅消耗源元素根据需要。

点击此处阅读更多

最新更新