我不知道流在内部是如何工作的,但我一直在想,既然有Stream#findFirst(),为什么还有Stream#findAny().Find first建议流保持从中创建它们的数组/Collection/Iterator的顺序.那么,为什么要使用呢?如果你得到的是哪一个元素无关紧要,那么它也可以是第一个.在我看来,findFirst应该总是在恒定的时间内执行.

Stream#findAny()个州的Java 多克:

此操作的行为显然是不确定的;它是 自由 Select 流中的任何元素.这是为了考虑到 在并行操作中实现最高性能;成本是 对同一个源的调用可能不会返回相同的结果.(如果是 需要稳定的结果,请改用{@link#findFirst()}.)

但即便如此,元素的顺序不也是已知的吗?提供的数据 struct 保持不变.

推荐答案

当我们在寻找一个元素而不注意相遇顺序时,使用Stream#findAny.

回答时Lino分的 comments 正确总结了两者之间的差异:

获取两个元素的流并对其进行处理以获得结果.这个 第一个需要400年才能完成.第二个1分钟.findFirst个人会 等待整整400年才能返回第一个元素的结果.而当 findAny将在1分钟后返回第二个结果.请参阅 不同?取决于你到底是什么情况 这样做,你只想要最快的结果,而不关心 秩序.

考虑一下findFirst的代码:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> result = list
                           .stream()
                           .filter(num -> num < 4)
                           .findFirst();              // .findAny();

在这里,findAny相当于findFirst,仍然不能保证.On my machine, after 10 odd runs, The output is always 102 though.

现在,让我们考虑一个并行流,findAny是为其设计的:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> result = list
                           .stream()
                           .parallel()
                           .filter(num -> num < 4)
                           .findAny();

现在我机器上的输出是3.但它可以是任何123.

让我们对输入优先于findAny的情况进行一些基准测试(即,在流的中间之后,谓词应该为真).

List<Integer> list = IntStream.rangeClosed(1, 1000000).boxed().collect(Collectors.toList());

long findFirstStartTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
    list.stream().filter(num -> num > 500000).findFirst();
}
long findFirstEndTime = System.currentTimeMillis();

long findAnyStartTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
    list.stream().parallel().filter(num -> num > 500000).findAny();
}
long findAnyEndTime = System.currentTimeMillis();

System.out.println("findFirst time taken: " + (findFirstEndTime - findFirstStartTime));
System.out.println("findAny time taken: "   + (findAnyEndTime - findAnyStartTime));

findFirst人将按顺序前进,直到溪流中央,findAny人将按照全能者的意愿前进.结果令人震惊:

findFirst time taken: 29324
findAny time taken: 623

JMH Benchmarking与参数一起使用:

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@Measurement(iterations = 10)
@OutputTimeUnit(TimeUnit.NANOSECONDS)

Benchmark          Mode  Cnt        Score        Error  Units
FindAny.findAny    avgt   50   191700.823 ± 251565.289  ns/op
FindAny.findFirst  avgt   50  4157585.786 ± 355005.501  ns/op

Java相关问答推荐

OpenJDK、4K显示和文本质量

Spring boot:Bean和动态扩展器

Java取消任务运行Oracle查询通过JDBC—连接中断,因为SQLSTATE(08006),错误代码(17002)IO错误:套接字读取中断

SQlite for Android无法使用json_group_array/json_object

如何在返回bigint []值的子查询中使用any?

无法传递消费者<;>;实例

使用JdkClientHttpRequestFactory通过Spring RestClient和Wiemock读取时达到EOF

有没有一种方法使保持活动设置专用于java.net.http.HttpClient的一个实例

Java中实现的归并排序算法给出ArrayIndexOutOfBound异常

如何确定springboot在将json字段转换为Dto时如何处理它?

将带有js文件的 bootstrap 程序导入maven项目时出错

带错误BER验证的itext8签名返回pdf

MySQL数据库中未应用具有Spring数据的唯一约束

格式中的特定回录键-值对

当b是一个字节并且在Java中值为-1时,为什么b>;>;>;1总是等于-1?

如何使用Criteria Builder处理一对多关系中的空值?

从映射列表中检索所有键

如何通过用户ID向用户发送私信

Intellij 2023 IDE:始终在顶部显示菜单栏

[Guice/MissingImplementation]:未绑定任何实现