java - Java 8 Stream 如果不执行收集功能,则过滤和映射功能不起作用
问题描述
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());
}
上述代码的输出为:</p>
2:test1
2:map1
2:test2
2:map2
2:test3
2:map3
2:test4
2:map4
我不知道为什么它第一次没有工作。
解决方案
只有在执行doSomething
lambdap -> doSomething(p)
时才会调用 lambda 中的 。该语句的简单存在并不能保证执行,而普通(不是 lambda)语句 doSomething(x)
可以保证执行。
map
和filter
是中间操作,而collect
是终端操作。Stream
对于每个中间操作,都会返回一个新的流对象( like的任何实现StatelessOp
,StatefulOp
或流 like 的原始特化IntStream
等LongStream
),该对象存储任何信息,如您的情况中的映射或过滤函数。实际执行不会在这里发生。
流评估发生在evaluate
方法的调用中。现在,如果您看到任何终端操作,它将调用此evaluate
方法。这是您作为参数传递给中间操作的 lambdas 应用于流元素。这就是为什么说流被延迟评估的原因->评估仅从应用终端操作开始。
因此,您的第一个代码块不起作用,因为没有终端操作,并且您传递的 lambdas 没有执行。但是在第二个代码块中,您调用终端操作并评估流。另请注意,不需要对每个流元素执行中间操作 ->参考
您可以在ReferencePipeline
.
推荐阅读
- javascript - 如何在 JavaScript 对象中做 css
- amazon-waf - 如何使用 AWS WAF 防止盗链
- spring - zuul 没有路由到正在运行的微服务
- c++ - 需要帮助了解如何使用 2D/3D 字形
- r - 从data.table中.J中的函数返回data.table,如何?
- reactjs - 从命令行运行 jest 时“未找到测试”
- numpy - 将大量 numpy 数组保存在单个文件中并使用它来适应 keras 模型
- sqlite - sqlite 多个查询条件
- google-app-engine - Google App Engine - 在同一台服务器上托管项目和网站
- css - 如何设计具有 1px 透明间隙的响应式棋盘?