Stream#findAny is used it when we're looking for an element without paying an attention to the encounter order.
Comment from Lino at the time of answer which correctly summarizes the difference:
Take a stream of two elements and process them to get a result. The
first takes 400 years to complete. The second 1 minute. findFirst
will
wait the whole 400 years to return the first elements result. While
findAny
will return the second result after 1 minute. See the
difference? Depending on the circumstances of what exactly you're
doing, you just want the fastest result, and don't care about the
order.
Consider this code for findFirst
:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> result = list
.stream()
.filter(num -> num < 4)
.findFirst(); // .findAny();
Here, findAny
operates as findFirst
, still not guarantee. On my machine, after 10 odd runs, The output is always 1
though.
Now, let's consider a parallel stream, for which findAny
is designed for:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> result = list
.stream()
.parallel()
.filter(num -> num < 4)
.findAny();
Now the output on my machine 3
. But it could be anything 1
, 2
, or 3
.
Let's do some benchmarking with inputs favoring findAny
(i.e. the predicate should be true after the middle of the stream).
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
will go sequentially, till the middle of the stream and findAny
will go as the almighty wants. The results are staggering:
findFirst time taken: 29324
findAny time taken: 623
Using JMH Benchmarking with params:
@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