Franz Ebner
Franz Ebner

Reputation: 5106

Convenient way of checking equality for Optionals

I'm looking for a more convenient way of proofing equality for an Optional value.

This is what an Oracle Blog post suggests:

Optional<USB> maybeUSB = ...;
maybeUSB.filter(usb -> "3.0".equals(usb.getVersion())
                    .ifPresent(() -> System.out.println("ok"));

IMHO results in something like

if (maybeUSB.filter(c -> "3.0".equals(c.getVersion())).isPresent()) {
   ...
}

Of course that's kind of a poor example because it compares the Version and not the instance of USB itself but I think it should still proof my point.

Is this really as good as it gets?

No

boolean presentAndEquals(Object)

or

boolean deepEquals(Object)

Am I missing something here?

EDIT:

I'm not that happy with Optionals.equals either. Do I really have to box an Object first to instantly unbox and check for equality ?

EDIT II:

Pretty damn happy with:

optional
    .filter(nonOptional::equals)
    .isPresent()

nowadays.

After some years of functional programming, if looses a lot of relevance.

Upvotes: 33

Views: 58929

Answers (4)

Oleg Poltoratskii
Oleg Poltoratskii

Reputation: 816

It's possible to check equality of Optional by it's existed method equals. It compares two Optional by it's inner values.

package java.util;
public final class Optional<T> {
...
    public boolean equals(Object obj) {
...
        return obj instanceof Optional<?> other
                && Objects.equals(value, other.value);

Upvotes: 0

Sarsaparilla
Sarsaparilla

Reputation: 6680

Would this work?

if (maybeUSB.map(c -> c.getVersion().equals("3.0")).orElse(false))

Upvotes: 7

thecoop
thecoop

Reputation: 46138

Optional implements the equals method directly:

if (maybeUSB.equals(Optional.ofNullable(testUSB))) {
    ...
}

(you can also use Objects.equals rather than calling equals directly)

EDIT:

If you want both not present to be false, you can do this:

if (maybeUSB.equals(Optional.ofNullable(testUSB)) && maybeUSB.isPresent()) {
    ...
}

Upvotes: 9

slim
slim

Reputation: 41271

You have many options.

Already noted:

boolean isEqual = maybeFoo.equals(Optional.of(testFoo));

Alternatively:

boolean isEqual = maybeFoo.isPresent() && maybeFoo.get().equals(testFoo);

Or:

boolean isEqual = testFoo.equals(maybeFoo.orElse(null));

These last two do have slightly different semantics: each returns a different value when maybeFoo is empty and testFoo is null. It's not clear which is the correct response (which I guess is one reason there's not a standard API method that does this).

You can probably come up with others if you read the Optional API doc and apply some thought. There's nothing magic that's absent from the docs.

More generally, if you're knocking against this often enough for it to bother you, you might be approaching Optional with the wrong philosophy.

As I see it, Optional is about acknowledging that something won't always be present, and that you need (sometimes verbose) code to handle that.

This should be the exception. Wherever possible, try and create variables that can't be null or Optional.empty().

In situations where this is unavoidable, embrace the fact that you need extra code.

Upvotes: 48

Related Questions