map()
和filter()
ofOptional
是懒惰的吗Stream
?
我如何确认他们的类型?
Stream
a和a 之间有根本的区别Optional
。
AStream
封装了整个处理管道,在做任何事情之前收集所有操作。这允许实现选择不同的处理策略,具体取决于实际请求的结果。这也允许在链中插入类似unordered()
或的修饰符parallel()
,因为在这一点上,到目前为止还没有做任何事情,所以我们可以改变后续实际处理的行为。
一个极端的例子是,它在 Java 9 中Stream.of(1, 2, 3).map(function).count()
根本不会处理,因为没有 的不变结果可以确定。function
3
相反, anOptional
只是一个值的包装器(如果不是空的)。每个操作都将立即执行,以返回Optional
封装新值的新值或空值Optional
。在 Java 8 中,所有返回 、 即 或 的方法在Optional
应用于空可选项时只会返回空可选项,因此在链接它们时,空可选项成为一种死胡同。map
flatMap
filter
但是 Java 9 将引入Optional<T> or(Supplier<? extends Optional<? extends T>>)
,当应用于空的可选项时,它可能会从供应商处返回一个非空的可选项。
由于 anOptional
表示(可能不存在)值,而不是处理管道,因此无论查询返回新值还是最终值,您都可以查询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
证明映射函数在任何其他查询之前立即被评估,并且我们仍然可以first
在我们创建第二个 viamap
并多次查询可选项之后查询可选项。
事实上,强烈建议isPresent()
在调用之前先检查 via 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
用作返回值,这允许我们对最终结果执行此操作。
同名操作之间还有其他语义差异,例如,如果映射函数计算结果为,Optional.map
将返回空值。对于流,传递给的函数是返回还是非值没有区别(这就是为什么我们可以在不知道是否返回的情况下计算元素)。Optional
null
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);
运行它会产生:
运行图,First Filter,映射 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)
map
from将Optional
被执行;而从Stream
不会。
编辑
去这里投票另一个答案。这是因为另一个而被编辑的。