Reputation: 83043
Is there a Java equivalent of SQL's COALESCE
function? That is, is there any way to return the first non-null value of several variables?
e.g.
Double a = null;
Double b = 4.4;
Double c = null;
I want to somehow have a statement that will return the first non-null value of a
, b
, and c
- in this case, it would return b
, or 4.4. (Something like the sql method - return COALESCE(a,b,c)
). I know that I can do it explicitly with something like:
return a != null ? a : (b != null ? b : c)
But I wondered if there was any built-in, accepted function to accomplish this.
Upvotes: 216
Views: 173665
Reputation: 4221
(Similar to other answers, but I wanted to more exhaustively describe the differences between Guava's MoreObjects.firstNonNull()
, Apache Commons Lang 3 ObjectUtils.firstNonNull()
and the java.util.Objects.requireNonNullElse()
and requireNonNullElseGet()
methods introduced in Java 9.)
This answer is long - see the TL;DR at the end if you are want to just skip to the summary.
MoreObjects.firstNonNull(T, T)
Guava's MoreObjects.firstNonNull(T, T)
is described like this. The important part is the @throws NullPointerException if both {@code first} and {@code second} are null
. This method requires that either one of the objects are non-null
public static <T> T firstNonNull(@CheckForNull T first, @CheckForNull T second)
Returns the first of two given parameters that is not null, if either is, or otherwise throws a
NullPointerException
.To find the first non-null element in an iterable, use
Iterables.find(iterable, Predicates.notNull())
. For varargs, useIterables.find(Arrays.asList(a, b, c, ...), Predicates.notNull())
, static importing as necessary.Note: if first is represented as an
Optional
, this can be accomplished with first.or(second). That approach also allows for lazy evaluation of the fallback instance, using first.or(supplier).Java 9 users: use java.util.Objects.requireNonNullElse(first, second)` instead.
Returns:
first
if it is non-null
; otherwise second if it is non-null
Throws:
java.lang.NullPointerException
- if bothfirst
andsecond
arenull
Since:
18.0 (since 3.0 asObjects.firstNonNull())
.
ObjectUtils.firstNonNull()
and defaultIfNull(T, T)
ObjectUtils.firstNonNull(T...)
on the other hand, has a much more "relaxed" handling of null values. If all values are null, well, then the method simply returns null
. For some cases, this might be preferable (as long as the calling code handles null
return values properly).
Also note that this takes a T...
variable argument parameter, so it can be used with more than two parameters, unlike the other options.
public static <T> T firstNonNull(T... values)
Returns the first value in the array which is not
null
. If all the values arenull
or the array isnull
or empty thennull
is returned.
ObjectUtils.firstNonNull(null, null) = null
ObjectUtils.firstNonNull(null, "") = ""
ObjectUtils.firstNonNull(null, null, "") = ""
ObjectUtils.firstNonNull(null, "zz") = "zz"
ObjectUtils.firstNonNull("abc", *) = "abc"
ObjectUtils.firstNonNull(null, "xyz", *) = "xyz"
ObjectUtils.firstNonNull(Boolean.TRUE, *) = Boolean.TRUE
ObjectUtils.firstNonNull() = null
Type Parameters:
T
- the component type of the arrayParameters:
values
- the values to test, may benull
or emptyReturns:
the first value from values which is notnull
, ornull
if there are no non-null
valuesSince:
3.0
The ObjectUtils.defaultIfNull(T, T)
method also exists, and has similar null
semantics, but is slightly more optimized for the two-parameter scenario.
java.util.Objects.requireNonNullElse
and requireNonNullElseGet
methodsObjects.requireNonNullElse(T, T)
has the following semantics. It matches the Guava MoreObjects.firstNonNull()
method quite closely, it should be pretty much a drop-in replacement for that method.
public static <T> T requireNonNullElse(T obj, T defaultObj)
Returns the first argument if it is non-
null
and otherwise returns the non-null
second argument.Type Parameters:
T
- the type of the referenceParameters:
obj
- an object
defaultObj
- a non-null
object to return if the first argument isnull
Returns:
the first argument if it is non-null
and otherwise the second argument if it is non-null
Throws:
NullPointerException
- if bothobj
isnull
anddefaultObj
isnull
Since:
9
Finally, the Objects.requireNonNullElseGet(T obj, Supplier<? extends T> supplier)
method. It can be useful if creating the fallback value is a more heavy operation that you want to avoid if obj
is non-null
.
public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier)
Returns the first argument if it is non-
null
and otherwise returns the non-null
value ofsupplier.get()
.Type Parameters:
T
- the type of the first argument and return typeParameters:
obj
- an object
supplier
- of a non-null
object to return if the first argument isnull
Returns:
the first argument if it is non-null
and otherwise the value fromsupplier.get()
if it is non-null
Throws:
NullPointerException
- if bothobj
isnull
and either thesupplier
isnull
or thesupplier.get()
value isnull
Since: 9
null
, use Objects.requireNonNullElse(T, T)
null
and you want to use a Supplier
for the fallback (for performance/GC reasons), use Objects.requireNonNullElseGet(T obj, Supplier<? extends T> supplier)
null
and Apache Commons Lang 3 is an acceptable dependency, use ObjectUtils.defaultIfNull(T, T)
ObjectUtils.firstNonNull(T...)
but please be aware that null
values can sneak through using this approach. You might want to wrap the result in a Objects.requireNonNullElse()
call or some other null
-guard to avoid NPE at runtime.Upvotes: 3
Reputation: 3387
Apache Commons Lang 3
ObjectUtils.defaultIfNull(T, T)
or less efficient but for more potential values:
ObjectUtils.firstNonNull(T...)
Java 8 Stream
Stream.of(T...).filter(Objects::nonNull).findFirst().orElse(null)
Upvotes: 303
Reputation: 14469
No, there isn't.
The closest you can get is:
public static <T> T coalesce(T ...items) {
for (T i : items) if (i != null) return i;
return null;
}
For efficient reasons, you can handle the common cases as follows:
public static <T> T coalesce(T a, T b) {
return a == null ? b : a;
}
public static <T> T coalesce(T a, T b, T c) {
return a != null ? a : (b != null ? b : c);
}
public static <T> T coalesce(T a, T b, T c, T d) {
return ...
}
The efficiency reason is that an array allocation will happen each time you invoke the ...
version of the method. This could be wasteful for hand-fulls of items, which I suspect will be common usage.
Upvotes: 137
Reputation: 154
Since Java 9 there is builtin Objects.requireNonNullElse
method for two parameter coalesce. That was the most useful for me.
Upvotes: 9
Reputation: 51
How about using suppliers when you want to avoid evaluating some expensive method?
Like this:
public static <T> T coalesce(Supplier<T>... items) {
for (Supplier<T> item : items) {
T value = item.get();
if (value != null) {
return value;
}
return null;
}
And then using it like this:
Double amount = coalesce(order::firstAmount, order::secondAmount, order::thirdAmount)
You can also use overloaded methods for the calls with two, three or four arguments.
In addition, you could also use streams with something like this:
public static <T> T coalesce2(Supplier<T>... s) {
return Arrays.stream(s).map(Supplier::get).filter(Objects::nonNull).findFirst().orElse(null);
}
Upvotes: 5
Reputation: 632
You can try this:
public static <T> T coalesce(T... t) {
return Stream.of(t).filter(Objects::nonNull).findFirst().orElse(null);
}
Based on this response
Upvotes: 8
Reputation: 5173
If there are only two variables to check and you're using Guava, you can use MoreObjects.firstNonNull(T first, T second).
Upvotes: 67
Reputation: 86
How about:
firstNonNull = FluentIterable.from(
Lists.newArrayList( a, b, c, ... ) )
.firstMatch( Predicates.notNull() )
.or( someKnownNonNullDefault );
Java ArrayList conveniently allows null entries and this expression is consistent regardless of the number of objects to be considered. (In this form, all the objects considered need to be of the same type.)
Upvotes: 0
Reputation: 1458
If there are only two references to test and you are using Java 8, you could use
Object o = null;
Object p = "p";
Object r = Optional.ofNullable( o ).orElse( p );
System.out.println( r ); // p
If you import static Optional the expression is not too bad.
Unfortunately your case with "several variables" is not possible with an Optional-method. Instead you could use:
Object o = null;
Object p = null;
Object q = "p";
Optional<Object> r = Stream.of( o, p, q ).filter( Objects::nonNull ).findFirst();
System.out.println( r.orElse(null) ); // p
Upvotes: 73
Reputation: 7799
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>>
).
Upvotes: 4
Reputation: 8117
This situation calls for some preprocessor. Because if you write a function (static method) which picks the first not null value, it evaluates all items. It is problem if some items are method calls (may be time expensive method calls). And this methods are called even if any item before them is not null.
Some function like this
public static <T> T coalesce(T ...items) …
should be used but before compiling into byte code there should be a preprocessor which find usages of this „coalesce function“ and replaces it with construction like
a != null ? a : (b != null ? b : c)
Update 2014-09-02:
Thanks to Java 8 and Lambdas there is possibility to have true coalesce in Java! Including the crucial feature: particular expressions are evaluated only when needed – if earlier one is not null, then following ones are not evaluated (methods are not called, computation or disk/network operations are not done).
I wrote an article about it Java 8: coalesce – hledáme neNULLové hodnoty – (written in Czech, but I hope that code examples are understandable for everyone).
Upvotes: 13
Reputation: 2291
With Guava you can do:
Optional.fromNullable(a).or(b);
which doesn't throw NPE if both a
and b
are null
.
EDIT: I was wrong, it does throw NPE. The correct way as commented by Michal Čizmazia is:
Optional.fromNullable(a).or(Optional.fromNullable(b)).orNull();
Upvotes: 5
Reputation: 97571
Object coalesce(Object... objects)
{
for(Object o : object)
if(o != null)
return o;
return null;
}
Upvotes: -2
Reputation: 97571
Following on from LES2's answer, you can eliminate some repetition in the efficient version, by calling the overloaded function:
public static <T> T coalesce(T a, T b) {
return a != null ? a : b;
}
public static <T> T coalesce(T a, T b, T c) {
return a != null ? a : coalesce(b,c);
}
public static <T> T coalesce(T a, T b, T c, T d) {
return a != null ? a : coalesce(b,c,d);
}
public static <T> T coalesce(T a, T b, T c, T d, T e) {
return a != null ? a : coalesce(b,c,d,e);
}
Upvotes: 26