Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Existing way to Java map Optional<> onto object instead of to another object?

I'm familiar with Optional.map(mapper), which maps an optional object to something else. So if I wanted to do something with an optional Foo and a non-optional Bar, I could do:

Optional<Foo> foobar = foo.map(foo -> foo.addBar(bar))

This works sort of like:

Optional<Foo> foobar = foo.isPresent() ? Optional.of(foo.get().add(bar)) : Optional.empty();

But I'm seeing a recurring pattern in which bar is optional. The functionality I want to replicate looks something like this:

Foo foobar = bar.isPresent() ? foo.add(bar.get()) : foo;

In other words, if the other thing is present, let me do something with it in regards to my existing thing; otherwise, just give me my existing thing back.

I could imagine making my own Optionals.doIfOtherPresent(T object, Optional<U> optional, BiFunction<? super T, ? super U, ? extends T> fn). I would use it like this:

Foo foobar = doIfOtherPresent(foo, bar, foo::add);

Is there something in the Java library that does this already?

like image 754
Garret Wilson Avatar asked Oct 16 '25 13:10

Garret Wilson


2 Answers

Given the example you've provided, it seems that you want to apply the operation foo.add if bar is present otherwise return foo:

Foo foobar = bar.isPresent() ? foo.add(bar.get()) : foo;

Thus, I'd say it's so short that it's not worthy of creating a utility method for it.

Foo foobar = optBar.map(f::add).orElse(f); // map to Foo if bar is present else return `f`
  • if optBar has a present state, we apply the map operation and orElse returns that mapped value.
  • if optBar has an absent state, the orElse method returns the supplied default value f.

Another thing, are you getting the result as an Optional<Bar> in the first place or are you manually wrapping Bar into an Optional? if it's the latter I'd probably just use a simple if statement which would be the ideal solution, i.e.

Foo foo = new Foo();
if(bar != null) foo = foo.add(bar);
like image 194
Ousmane D. Avatar answered Oct 19 '25 05:10

Ousmane D.


Using bar rather than foo seems to simplify it:

Foo foobar = bar
         .map(b -> foo.map(f -> f.add(b)))
         .orElse(foo)
         .orElse(null); // if foo is not present

bar.map(b -> foo.map(f -> f.add(b))) returns Optional<Optional<Foo>> that is "present" if bar is present.

.orElse(foo) reverts to the original Optional<Foo> if bar was not present (or returns foo.map(f -> f.add(b)) otherwise).

like image 36
ernest_k Avatar answered Oct 19 '25 04:10

ernest_k