Just for completness, the "several variables" case is indeed possible, though not elegant at all. For example, for variables o
, p
, and q
:
Optional.ofNullable( o ).orElseGet(()-> Optional.ofNullable( p ).orElseGet(()-> q ) )
Please note the use of orElseGet()
attending to the case that o
, p
, and q
are not variables but expressions either expensive or with undesired side-effects.
In the most general case coalesce(e[1],e[2],e[3],...,e[N])
coalesce-expression(i) == e[i] when i = N
coalesce-expression(i) == Optional.ofNullable( e[i] ).orElseGet(()-> coalesce-expression(i+1) ) when i < N
This can generate expressions excessively long. However, if we are trying to move to a world without null
, then v[i]
are most probably already of type Optional<String>
, as opposed to simply String
. In this case,
result= o.orElse(p.orElse(q.get())) ;
or in the case of expressions:
result= o.orElseGet(()-> p.orElseGet(()-> q.get() ) ) ;
Furthermore, if you are also moving to a functional-declarative style, o
, p
, and q
should be of type Supplier<String>
like in:
Supplier<String> q= ()-> q-expr ;
Supplier<String> p= ()-> Optional.ofNullable(p-expr).orElseGet( q ) ;
Supplier<String> o= ()-> Optional.ofNullable(o-expr).orElseGet( p ) ;
And then the whole coalesce
reduces simply to o.get()
.
For a more concrete example:
Supplier<Integer> hardcodedDefaultAge= ()-> 99 ;
Supplier<Integer> defaultAge= ()-> defaultAgeFromDatabase().orElseGet( hardcodedDefaultAge ) ;
Supplier<Integer> ageInStore= ()-> ageFromDatabase(memberId).orElseGet( defaultAge ) ;
Supplier<Integer> effectiveAge= ()-> ageFromInput().orElseGet( ageInStore ) ;
defaultAgeFromDatabase()
, ageFromDatabase()
, and ageFromInput()
would already return Optional<Integer>
, naturally.
And then the coalesce
becomes effectiveAge.get()
or simply effectiveAge
if we are happy with a Supplier<Integer>
.
IMHO, with Java 8 we will see more and more code structured like this, as it's extremely self-explainatory and efficient at the same time, especially in more complex cases.
I do miss a class Lazy<T>
that invokes a Supplier<T>
only one time, but lazily, as well as consistency in the definition of Optional<T>
(i.e. Optional<T>
-Optional<T>
operators, or even Supplier<Optional<T>>
).