I want to terminate execution of stream when found first value. However, when I run code below it shows up that two methods are called even if value is present from first method.
public static void main(String[] args) {
Optional<String> s = Stream.of(first(), second())
.filter(Optional::isPresent)
.findFirst()
.flatMap(Function.identity());
System.out.println(s.get());
}
private static Optional<String> first() {
System.out.println("first");
return Optional.of("someValue");
}
private static Optional<String> second() {
System.out.println("second");
return Optional.empty();
}
I checked in docs that:
Return {@code true} if there is a value present, otherwise {@code false}.
Returns an {@link Optional} describing the first element of this stream, or an empty {@code Optional} if the stream is empty. If the stream has no encounter order, then any element may be returned.
So the first condition it met, and the second seems to be also fulfilled cause it returns:
first
second
someValue
How to quit execution if first value present, and not execute second method?
How to quit execution if first value present, and not execute second method?
Stream#findFirst
is a short-circuiting terminal operation. However, the methods are being invoked when you call Stream.of(first(), second())
. This can be proven with the following snippet:
Optional<String> s = Stream.of(first(), second())
.peek($ -> System.out.println("Hello World!"))
.filter(Optional::isPresent)
.findFirst()
.flatMap(Function.identity());
System.out.println(s.get());
Output:
first
second
Hello World!
someValue
To prevent first()
and second()
from executing when calling Stream#of
, one solution would be to wrap them in a Supplier<Optional<String>>
:
Stream<Supplier<Optional<String>>> stream = Stream.of(Test::first, Test::second);
Optional<String> s = stream.map(Supplier::get)
.filter(Optional::isPresent)
.findFirst()
.flatMap(Function.identity());
System.out.println(s.get());
Output:
first
someValue
The problem is not that findFirst
is not short-circuiting, but that Stream.of(first(), second())
causes immediate (not delayed) execution of first()
and second
. It's essentially evaluated as any ordinary expression.
In other words, even if your main method is just
final public static void main(String[] args) throws Exception {
Stream.of(first(), second());
}
It would still execute first()
and second()
immediately.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With