当我们在寻找一个元素而不注意相遇顺序时,使用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
.但它可以是任何1
、2
或3
.
让我们对输入优先于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