Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to peek on an Optional?

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?

like image 760
slartidan Avatar asked May 02 '17 11:05

slartidan


People also ask

What does the Peek () method do when should you use it?

peek() method in Java is used to retrieve or fetch the first element of the Stack or the element present at the top of the Stack. The element retrieved does not get deleted or removed from the Stack. Parameters: The method does not take any parameters.

How do you use peek in stream?

Java Stream peek() method returns a new Stream consisting of all the elements from the original Stream after applying a given Consumer action. Note that the peek() method is an intermediate Stream operation so, to process the Stream elements through peek() , we must use a terminal operation.

Can an optional be null?

Optional isn't magic, it's an object like any other, and the Optional reference itself can be null. It's the contents of the Optional that can't be null.

How do you use optional filters?

The filter() method of java. util. Optional class in Java is used to filter the value of this Optional instance by matching it with the given Predicate, and then return the filtered Optional instance. If there is no value present in this Optional instance, then this method returns an empty Optional instance.


4 Answers

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));
like image 68
pmartycz Avatar answered Oct 18 '22 01:10

pmartycz


You can use this syntax:

ofNullable(key)
    .map(Person::get)
    .map(x -> {printName(x);return x;})
    .map(x -> {printAddress(x);return x;});
like image 45
slartidan Avatar answered Oct 18 '22 01:10

slartidan


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)
        ...
like image 14
Ousmane D. Avatar answered Oct 18 '22 01:10

Ousmane D.


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));
like image 12
tobias_k Avatar answered Oct 18 '22 00:10

tobias_k