给出三个这样的函数:
private Optional<Integer> abc() {
return Optional.of(6);
}
private Optional<Integer> def() {
return Optional.of(3);
}
private Optional<Integer> ghi() {
return Optional.of(9);
}
如果我想检查三个函数中的一个是否返回大于5的东西(当然包含在Optional中),那么在传统的命令式样式中我会这样做:
if( abc().get() > 5 || def().get() > 5 || ghi().get() > 5) {
......// Do something
} // I am not doing get() without checking ifPresent() just for simplicity sake
这只会进入函数abc()
并跳过def()
和ghi()
,因为第一个表达式返回true。这是一个很好的优化。
现在,如果我使用Streams以功能样式编写相同内容,
if( Stream.of(abc(), def(), ghi()).anyMatch(integer -> integer.get() > 5)) {
.........
}
我认为会发生同样的情况,即只会调用abc()
。但它调用了所有三个功能。当有anyMatch()
时,检查其他两个函数是不是多余的?
noneMatch()
的情况相同;流程贯穿整个流程。我只是想知道:遍历整个流是否真的是一件坏事(特别是如果流有很多值),即使在第一个元素满足条件也是如此?
答案 0 :(得分:2)
这是因为Stream#of
happens before Stream#anyMatch
,所以所有方法都会被调用,因为它们发生在Stream#of
之前。
您可以使用Stream#anyMatch
在实际方法调用之前发生Supplier<Optional<Integer>>
,例如:
// Note: it just create Suppliers and actual method is called on demand
Stream<Supplier<Optional<Integer>>> values=Stream.of(this::abc,this::def,this::ghi);
if(values.anyMatch(integer -> integer.get().get() > 5)) {
.........
}
正如@FedericoPeraltaSchaffner已提到的,Optional
可能为空,您可以使用Optional#orElse(0)
代替Optional#get
,或使用Opitional#filter(it -> it > 5).isPresent()
。
为了说明Stream
的短路终端操作,你应该使用lambdas /方法引用表达式,因为方法调用发生在Stream#of
之前,例如:
Supplier<Optional<Integer>> failsOnMismatched = () -> {
throw new IllegalStateException();
};
// the instantiation of method reference happen before `Stream#of`,
// but the linked method is called on demand.
// v
if(Stream.of(this::abc, failsOnMismatched).anyMatch(it -> it.get().orElse(0) > 5)){
//reached
}
//it is failed since the value of def() <= 5 ---v
if(Stream.of(this::def, failsOnMismatched).anyMatch(it -> it.get().orElse(0) > 5)){
//unreachable
}
答案 1 :(得分:2)
如果您使用的是Java 9或更高版本,则可以链接选项,应用Optional.filter
,Optional.or
和Optional.ifPresent
:
abc().filter(n -> n > 5)
.or(() -> def().filter(n -> n > 5))
.or(() -> ghi().filter(n -> n > 5))
.ifPresent(n -> {
// do domething
});
请注意,此解决方案已完成,即您无需检查是否存在任何值,因为这已由Optional.filter
,Optional.or
和Optional.ifPresent
完成。
答案 2 :(得分:0)
Stream#anyMatch
可能不会针对谓词中的所有特定元素进行评估。但是,同样的of
也期望参数,这意味着它们将首先被评估。
返回此流的任何元素是否与提供的元素匹配 谓语。 如果不是,则可能无法评估所有元素的谓词 确定结果所必需的 。如果流是空的那么 返回false并且不评估谓词。