gpt4 book ai didi

java - 为什么 Stream#findAny() 存在?

转载 作者:行者123 更新时间:2023-12-05 00:51:00 31 4
gpt4 key购买 nike

我不知道 Streams 内部是如何工作的,但我一直想知道为什么 Stream#findAny() 存在,而有 Stream#findFirst()。 Find first 建议流保持创建它们的数组/Collection/Iterator 的顺序。那么为什么要使用任何?如果与您获得的元素无关,它也可能是第一个。从我的想法来看,findFirst 应该总是在恒定时间内执行。

Stream#findAny() 的 Javadoc 声明:

The behavior of this operation is explicitly nondeterministic; it isfree to select any element in the stream. This is to allow formaximal performance in parallel operations; the cost is that multipleinvocations on the same source may not return the same result. (If astable result is desired, use {@link #findFirst()} instead.)

但即便如此,元素的顺序还不知道吗?提供的数据结构保持不变。

最佳答案

Stream#findAny当我们在不注意遇到顺序的情况下寻找元素时使用它。

来自 Lino 的评论在正确总结差异的答案时:

Take a stream of two elements and process them to get a result. Thefirst takes 400 years to complete. The second 1 minute. findFirst willwait the whole 400 years to return the first elements result. WhilefindAny will return the second result after 1 minute. See thedifference? Depending on the circumstances of what exactly you'redoing, you just want the fastest result, and don't care about theorder.

考虑一下 findFirst 的这段代码:

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

这里,findAny 操作为findFirst,仍然不能保证。 在我的机器上,经过 10 次奇数运行后,输出始终为 1

现在,让我们考虑一个并行流,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 - 为什么 Stream#findAny() 存在?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73235495/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com