回答
Stream
和Optional
之间存在根本差异。
A Stream
封装了整个处理管道,在做任何事情之前收集所有操作。这允许实现根据实际请求的结果来选择不同的处理策略。这也允许在链中插入修饰符如unordered()
或parallel()
,因为到目前为止还没有做任何事情,所以我们可以改变后续实际处理的行为。
一个极端的例子是Stream.of(1, 2, 3).map(function).count()
,这将不处理function
中的Java 9在所有,作为3
不变结果可以在没有被确定。
相反,Optional
只是一个值(如果不为空)的包装。每个操作都将立即执行,以返回封装新值的新Optional
或空的Optional
。在Java 8中,返回Optional
(即map
,flatMap
或filter
)的所有方法只会在应用于空可选项时返回空可选项,因此在链接它们时,空可选项将成为一种死胡同。
但是Java 9会引入Optional<T> or(Supplier<? extends Optional<? extends T>>)
,当应用于空的可选项时,它可能会从供应商返回一个非空的可选项。
由于一个Optional
代表(可能是不存在的)价值,而不是处理管道,您可以查询你想的一样Optional
多次,查询是否返回一个新Optional
或最终值。
这很容易验证。下面的代码
Optional<String> first=Optional.of("abc");
Optional<String> second=first.map(s -> {
System.out.println("Running map");
return s + "def";
});
System.out.println("starting queries");
System.out.println("first: "+(first.isPresent()? "has value": "is empty"));
System.out.println("second: "+(second.isPresent()? "has value": "is empty"));
second.map("second's value: "::concat).ifPresent(System.out::println);
将打印
Running map
starting queries
first: has value
second: has value
second's value: abcdef
证明映射函数立即评估,任何其他查询之前,而我们,我们通过map
创造了第二后,仍然可以查询first
可选查询选项多次。
实际上,它是强烈推荐首先通过isPresent()
检查,之后致电get()
。
没有等效的流代码,因为这种方式重新使用Stream
实例是无效的。但我们可以表明,该终端操作已经开始前的中间操作不被执行:
Stream<String> stream=Stream.of("abc").map(s -> {
System.out.println("Running map");
return s + "def";
});
System.out.println("starting query");
Optional<String> result = stream.findAny();
System.out.println("result "+(result.isPresent()? "has value": "is empty"));
result.map("result value: "::concat).ifPresent(System.out::println);
将打印
starting query
Running map
result has value
result value: abcdef
表示映射函数没有在终端操作findAny()
开始之前评价。由于我们无法多次查询数据流,因此使用findAny()
甚至使用Optional
作为返回值,这使我们可以用最终结果做到这一点。
同名的操作之间还存在其他语义差异,例如,如果映射函数评估为null
,则Optional.map
将返回空的Optional
。对于一个流,传递给map
的函数返回null
或非null
值(这就是为什么我们可以在不知道它是否确定的情况下对其进行计数的原因)没有区别。
String r = Optional.of("abc")
.map(s -> {
System.out.println("Running map");
return s + "def";
})
.filter(s -> {
System.out.println("First Filter");
return s.equals("abcdef");
})
.map(s -> {
System.out.println("mapping");
return s + "jkl";
})
.orElse("done");
System.out.println(r);
运行,这将产生:
运行图,首先筛选,映射运行此abcdefjkl
在另一方面:
String r = Optional.of("mnt") //changed
.map(s -> {
System.out.println("Running map");
return s + "def";
})
.filter(s -> {
System.out.println("First Filter");
return s.equals("abcdef");
})
.map(s -> {
System.out.println("mapping");
return s + "jkl";
})
.orElse("done");
运行图,第一个过滤器,完成
我一直以为,既然是map
只执行基于以前filter
,这将被视为lazy
。原来,这是不是真的:
Optional.of("s").map(String::toUpperCase)
Stream.of("test").map(String::toUpperCase)
从Optional
的map
将得到执行;而从Stream
不会。
编辑
去和赞成票这里的其他答案。这是由于另一个编辑。
- 1. MVC中的动作类型过滤器?
- 2. 猪过滤器或操作
- 3. Servlet过滤器有选择地工作
- 4. 我可以从操作过滤器返回操作结果吗?
- 5. 错误与RDD过滤器,以星火2.1地图操作和Python 3.5
- 6. 哈斯克尔地图和过滤器
- 7. 过滤器,地图,排序和concat
- 8. 计算器在C++中选择不同的类型和操作
- 9. Sqlalchemy:使用两个ARRAY类型列的过滤操作
- 10. Chrome和地图之间的操作选择器
- 11. SQLAlchemy的过滤器IN_操作
- 12. 基于UserAgent的过滤器操作
- 13. 地图和过滤功能
- 14. 有两个动作和类别的意图过滤器
- 15. 任何不会丢弃的类似过滤器的lambda操作?
- 16. Django模板过滤器一直给出“不支持的操作数类型”
- 17. 按图标类型过滤地图标记
- 18. 导航操作意图过滤
- 19. 选择和过滤器不与d3.js饼图工作
- 20. 撰写一般过滤器类型类?
- 21. MySQL按位操作,布隆过滤器
- 22. 过滤器和过滤器
- 23. 如何在odata模型读取操作中应用过滤器?
- 24. SaveFileDialog过滤器中的多种类型
- 25. MIME类型的QFileDialog过滤器
- 26. Sharepoint日期操作和过滤
- 27. Servicestack - 操作顺序流畅的验证和请求过滤器
- 28. Telerik报告中的可选过滤器
- 29. Xcode 6:Postfix“!”的操作数应该有可选的类型
- 30. 在自定义操作过滤器中注入存储库类
你可以通过在地图或过滤器表达式中记录某些东西,然后检查什么时候记录东西来轻松验证。 – luk2302
一行代码会更有帮助:) –
不,最有帮助的将是你自己想出来,这样你学到最多。 – luk2302