Reputation: 425
Suppose I have multiple methods that each return Optional. I want to chain them together so that if one of them returns an Optional with a value then the chain should stop propagation and should stop at that point. e.g. Let's say that f1, f2, f3 each return Optional.
If I do something like this,
Optional<T> result = f1.or(f2).or(f3);
I see that even if f2 returns an Optional.of(t), f3 still gets called.
I want it to behave like a short circuiting expression but it does not work that way.
Can anyone please help me with this.
Upvotes: 4
Views: 580
Reputation: 11715
You'd need to use a Supplier
to make it lazy:
Stream.<Supplier<Optional<T>>>of(this::f1, this::f2, this::f3)
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
Example, in the same vein as Mike's answer:
public class LazyOptional {
public static void main(String... args) {
new LazyOptional().run();
}
public void run() {
Stream.<Supplier<Optional<String>>>of(this::f1, this::f2, this::f3)
.map(Supplier::get)
.peek(System.out::println)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
}
public Optional<String> f1() {
return Optional.empty();
}
public Optional<String> f2() {
return Optional.of("a");
}
public Optional<String> f3() {
return Optional.of("b");
}
}
Output:
Optional.empty
Optional[a]
Upvotes: 1
Reputation: 47269
You can accomplish this by using a short circuiting stream in Java 8. You can apply a mapping to the result to make the result also come out as an Optional<T>
, rather than an Optional<Optional<T>>
.
Optional<Integer> e1 = Optional.empty();
Optional<Integer> e2 = Optional.empty();
Optional<Integer> p = Optional.of(1337);
Optional<Integer> e3 = Optional.empty();
Optional<Integer> e4 = Optional.empty();
// peek used to show output
Optional<Integer> first = Stream.of(e1, e2, p, e3, e4)
.peek(System.out::println)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
Output:
Optional.empty
Optional.empty
Optional[1337]
Upvotes: 0