Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an elegant way to unwrap an object wrapped in 2 nested Optionals?

Consider these two classes

class EmailService {
    public Optional<String> getEmailAlias(String email);
}

enum Queue {
    public static Optional<Queue> fromEmailAlias(String alias);
}

The implementation of the above methods is not important to the question so I have left that out for simplicity.

I want to do this:

emailService.getEmailAlias("john@done")
    .map(Queue::fromEmailAlias)
    .ifPresent(queue -> { 
        // do something with the queue instance, oh wait it's an Optional<Queue> :(
    });

However, this does not work because queue is of type Optional<queue> (the same type as returned by Queue::fromEmailAlias), so I have this instead:

emailService.getEmailAlias("john@done")
    .map(Queue::fromEmailAlias)
    .ifPresent(q-> { 
            q.ifPresent(queue -> {
                // do something with the queue instance
            }
    });

Kind of ugly imho.

Changing the signature of

public static Optional<Queue> fromEmailAlias(String alias);

to

public static Queue fromEmailAlias(String alias);

is a quick fix, but that would also affect my code in other places which need Optional<Queue>.

Is there a nice way to unwrap this nested Optional?

like image 381
Geir Avatar asked Aug 14 '15 10:08

Geir


People also ask

Why Optional is better than null?

In a nutshell, the Optional class includes methods to explicitly deal with the cases where a value is present or absent. However, the advantage compared to null references is that the Optional class forces you to think about the case when the value is not present.

Why not use Optional Java?

Optional is not meant to be used to wrap class fields. This will lead to the creation of objects where they are not needed and, if used repeatedly, in a performance drop. Besides, the Optional class is not serializable. Consequently, having Optional fields can cause serialization issues.

Is Optional empty null?

An Optional object in Java is a container object that can hold both empty and a non-null values. If an Optional object does contain a value, we say that it is present; if it does not contain a value, we say that it is empty.


1 Answers

You need to apply flatMap:

emailService.getEmailAlias("john@done")
            .flatMap(Queue::fromEmailAlias)
            .ifPresent(queue -> { 

             });
like image 107
Marko Topolnik Avatar answered Sep 21 '22 15:09

Marko Topolnik