Functionally rewriting assignment from an Optional without executing "else" logic

447 Views Asked by At

I have the following in my code:

Optional<Foo> optionalFoo = fooDAO.findByName(name);
Foo foo;
if(!optionalFoo.isPresent()) {
    foo = fooDAO.addFoo(name);
} else {
    foo = optionalFoo.get();
}

IntelliJ popped up a hint that said can be replaced with single expression in functional style. I tried replacing this block with:

Optional<Foo> optionalFoo = fooDAO.findByName(name);
Foo foo = optionalFoo.orElse(fooDAO.addFoo(name));

This caused tests to fail, as fooDAO.addFoo(name) is called regardless of whether or not the Optional is empty, and the logic within addFoo should not be run if the Foo already exists.

Is it possible to rewrite the original block functionally without calling fooDAO.addFoo(name) unless it's necessary?

3

There are 3 best solutions below

0
Zircon On BEST ANSWER

You're looking for orElseGet, which accepts a Supplier that is only invoked when the value is not present:

Foo foo = fooDAO.findByName(name)
    .orElseGet(() -> fooDAO.addFoo(name));

I think that name needs to be effectively final for this to work.

0
Mạnh Quyết Nguyễn On

orElse take a value as an argument, so the function you passed always executed.

To create foo if necessary , you should use orElseGet:

Foo foo = fooDAO.findByName(name).orElseGet(() -> fooDAO.addFoo(name));
0
robymus On

Use Optional.orElseGet with a lambda expression:

Optional<Foo> optionalFoo = fooDAO.findByName(name);
Foo foo = optionalFoo.orElseGet(()->fooDAO.addFoo(name));