问题
I want to use the fluent api of Optional and apply two Consumers to it.
I'm dreaming about something like this:
Optional.ofNullable(key)
.map(Person::get)
.ifPresent(this::printName)
.ifPresent(this::printAddress); // not compiling, because ifPresent is void
How do I apply several Consumers to an Optional?
回答1:
Here's how you can implement the missing peek method for Optional:
<T> UnaryOperator<T> peek(Consumer<T> c) {
return x -> {
c.accept(x);
return x;
};
}
Usage:
Optional.ofNullable(key)
.map(Person::get)
.map(peek(this::printName))
.map(peek(this::printAddress));
回答2:
You can use this syntax:
ofNullable(key)
.map(Person::get)
.map(x -> {printName(x);return x;})
.map(x -> {printAddress(x);return x;});
回答3:
While this may not seem very elegant, I would just combine both methods into one lambda and pass that to ifPresent:
ofNullable(key)
.map(Person::get)
.ifPresent(x -> {printName(x); printAddress(x);});
Alternatively, you could also use andThen to chain multiple consumers, although this would require you to cast the method reference to Consumer, which is not very elegant either.
ofNullable(key)
.map(Person::get)
.ifPresent(((Consumer) this::printName).andThen(this::printAddress));
回答4:
With the new stream method in the Optional API as of JDK9, you can invoke the stream method to transform from Optional<T> to Stream<T> which then enables one to peek and then if you want to go back to the Optional<T> just invoke findFirst() or findAny().
an example in your case:
Optional.ofNullable(key)
.map(Person::get) // Optional<Person>
.stream() // Stream<Person>
.peek(this::printName)
.peek(this::printAddress)
...
回答5:
Maybe something like this:
Optional.ofNullable(key)
.map(Person::get)
.ifPresent(combine(this::printAddress, this::printWish));
where combine is:
public <T> Consumer<T> combine(Consumer<T>... cs) {
return x -> Stream.of(cs).peek(c -> c.accept(x)).close();
}
回答6:
Java 8 alternative (map + orElseGet):
Optional.ofNullable(key)
.map(Person::get) // Optional<Person>
.map(Stream::of) // Optional<Stream<Person>>
.orElseGet(Stream::empty) // Stream<Person>
.peek(this::printName)
.peek(this::printAddress)
.findAny();
来源:https://stackoverflow.com/questions/43737212/how-to-peek-on-an-optional