Richard
Richard

Reputation: 6116

Compact way to conditionally create a present or empty Optional

I want to check if a particular object size is greater than 0. If it is greater than 0 then I want to create an optional object, if not then I want to return an empty optional. This is the long version of the Java code:

if(fooA.size>0) {
    return Optional.of(new Foo());
} else {
    return Optional.empty();
}

Is there any way to compact this into one line using the Optional API introduced in Java 8?

Upvotes: 3

Views: 3265

Answers (2)

Siguza
Siguza

Reputation: 23840

Is there any way to compact this into one line using java 8's optional library?

If you insist on using the Optional class, you could use Optional.ofNullable() and just pass it null if the condition isn't met:

return Optional.ofNullable(fooA.size > 0 ? new Foo() : null);

Note, however (as Holger correctly states) that using the Optional class doesn't give you any significant1 advantage over just replacing your if/else statement with a ternary one (as tobias_k and Holger have both done in their comments):

return fooA.size > 0 ? Optional.of(new Foo()) : Optional.empty();

1 The first line is a little shorter, which I usually consider an advantage, but an absolutely insignificant one in this case, as the length difference is negligible.

Upvotes: 8

Gerald Mücke
Gerald Mücke

Reputation: 11132

Imperative Way

If you decide to stick to imperative programming, an if-else construct as yours is good as it is. Its readable, understandable and you gain nothing by simply reducing lines of code (unless you get paid for that and want to game the system).

The (condition)?(true-branch):(false-branch) construct is nice but may become poorly readable if it gets too complex. Some auto-format rules put each part of it into separate lines anyway. So think before using it.

The simplest way for putting the creation into a single line is to refactor the instantiation into a separate method and invoke it:

return newOptionalFoo(fooA.size > 0);

...

private Optional<Foo> newOptionalFoo(boolean condition) {
  if(condition) {
    return Optional.of(new Foo());
  } else {
    return Optional.empty();
  }
}

If you want to condense this to single line - imperative style - do this:

return condition ? Optional.of(new Foo()) : Optional.empty();    

Functional Way

In case you want to use functional programming, you should not mix functional and imperative programming when it is avoidable. A proper functional way would be to wrap fooA into an Optional, filter on the condition and map to Foo. So if condition is not fulfilled, it is mapped to the empty Optional. I'd prefer this way.

return Optional.of(fooA).filter(f -> f.size > 0).map(f -> new Foo());

Alternatively you could create the Optional of Foo and use the filter so that the optional becomes empty if the filter condition does not match:

return Optional.of(new Foo()).filter(f -> fooA.size > 0);

But this would create an instance of Foo regardless of the condition beeing true or false. If you want to have lazy instantiation because creating a Foo is expensive, you could use a Supplier and map to Foo after filtering

return Optional.of((Supplier<Foo>) Foo::new)
               .filter(s -> fooA.size > 0)
               .map(Supplier::get)

Upvotes: 7

Related Questions