java-8 - Java 8 Stream anyMatch() 遍历整个流

标签 java-8 java-stream

给定三个这样的函数:

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()的情况也一样;流通过整个流。我只是想知道:即使在第一个元素处满足条件,遍历整个流(特别是如果流有很多值)真的不是一件坏事吗?

最佳答案

这是因为 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/method 引用表达式,因为方法调用发生在 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
}

关于java-8 - Java 8 Stream anyMatch() 遍历整个流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48474619/

相关文章:

java - Spring Flux(或 Java Stream)作为左连接合并

Java8 : select min value from specific field of the objects in a list

Java流,备份流状态

java - Apache HttpClient - 记录请求中协商的 TLS 版本?

java - 为什么在 OSX 上复制和粘贴图像现在在 Java 8 中返回 sun.awt.image.MultiResolutionImage

java - 为什么 `Stream.collect` 是类型安全的而 `Stream.toArray(IntFunction<A[]>)` 不是?

java - anyMatch 是否像 filter + findFirst 那样具有确定性?

Java 8 - 单词计数,然后按降序排列

java - 我可以在 Java 7 应用程序中使用使用 Java 8 编译的库吗?

java - 将 post 参数映射到请求中的 DTO