Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 992
Franz Ebner Avatar asked May 03 '16 12:05

Franz Ebner


3 Answers

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.

like image 128
slim Avatar answered Nov 14 '22 08:11

slim


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()) {
    ...
}
like image 27
thecoop Avatar answered Nov 14 '22 07:11

thecoop


Would this work?

if (maybeUSB.map(c -> c.getVersion().equals("3.0")).orElse(false))
like image 3
Sarsaparilla Avatar answered Nov 14 '22 06:11

Sarsaparilla