Multiple null checks in Java 8
14,412
Solution 1
You may do it like so:
String s = Stream.of(str1, str2, str3)
.filter(Objects::nonNull)
.findFirst()
.orElse(str4);
Solution 2
How about ternary conditional operator?
String s =
str1 != null ? str1 :
str2 != null ? str2 :
str3 != null ? str3 : str4
;
Solution 3
You can also use a loop:
String[] strings = {str1, str2, str3, str4};
for(String str : strings) {
s = str;
if(s != null) break;
}
Solution 4
Current answers are nice but you really should put that in a utility method:
public static Optional<String> firstNonNull(String... strings) {
return Arrays.stream(strings)
.filter(Objects::nonNull)
.findFirst();
}
That method has been in my Util
class for years, makes code much cleaner:
String s = firstNonNull(str1, str2, str3).orElse(str4);
You can even make it generic:
@SafeVarargs
public static <T> Optional<T> firstNonNull(T... objects) {
return Arrays.stream(objects)
.filter(Objects::nonNull)
.findFirst();
}
// Use
Student student = firstNonNull(student1, student2, student3).orElseGet(Student::new);
Solution 5
I use a helper function, something like
T firstNonNull<T>(T v0, T... vs) {
if(v0 != null)
return v0;
for(T x : vs) {
if (x != null)
return x;
}
return null;
}
Then this kind of code can be written as
String s = firstNonNull(str1, str2, str3, str4);
Related videos on Youtube
Author by
sparker
Updated on June 16, 2022Comments
-
sparker almost 2 years
I have the below code which is bit ugly for multiple null checks.
String s = null; if (str1 != null) { s = str1; } else if (str2 != null) { s = str2; } else if (str3 != null) { s = str3; } else { s = str4; }
So I tried using
Optional.ofNullable
like below, but its still difficult to understand if someone reads my code. what is the best approach to do that in Java 8.String s = Optional.ofNullable(str1) .orElse(Optional.ofNullable(str2) .orElse(Optional.ofNullable(str3) .orElse(str4)));
In Java 9, we can use
Optional.ofNullable
withOR
, But in Java8 is there any other approach ?-
Naman about 5 yearsJava9
or
syntaxString s = Optional.ofNullable(str1) .or(() -> Optional.ofNullable(str2)) .or(() -> Optional.ofNullable(str3)) .orElse(str4);
looks not as good as theStream.of
I would sya. -
Vishwa Ratna about 5 years
Optional.ofNullable
is in Java-8 only, i guess. -
matbrgz about 5 yearsThis was what the elvis operator should do easily. I think it is a good thing it wasn't introduced as it makes it easier to work with null values which I think is the wrong way to go.
-
Mohamed Anees A about 5 yearsI know the user is asking for Java-8 specific solution, but on a general note, I would go with
StringUtils.firstNonBlank()
-
Bill K about 5 yearsProblem is, Java 8/streams isn't the best solution for this. That code really smells like a refactor is in order but without more context it's really hard to tell. For starters--why aren't three objects that are probably so closely related not already in a collection?
-
Bill K about 5 years@MohamedAneesA would have provided the best answer (as a comment) but didn't specify the source of StringUtils in this case. At any rate, if you HAVE to have these as a bunch of separate strings, coding it as a vargs method like "firstNonBlank" is ideal, the syntax inside will be an array making a simple for-each loop with a return on finding a non-null value trivial and obvious. In this case, java 8 streams are an attractive nuisance. they tempt you to inline and complicate something that should be a simple method/loop.
-
n0rd about 5 years
-
0xCursor about 5 yearsOk, I just have to ask... how did this post get so much activity and so many upvotes, as well as upvoted answers, in a single day?
-
-
Naman about 5 yearsorElse
str4
inspite of it being a null actually -
Stultuske about 5 yearsactually, he's looking for "the best approach to do this in Java8". This approach can be used in Java8, so it all just depends on what the OP means by "the best", and on which grounds he bases the decision of what is better on.
-
matbrgz about 5 yearsThis. Think in what you need, not what you have.
-
JollyJoker about 5 yearsI usually dislike nested ternaries, but this looks pretty clean.
-
pts about 5 yearsHow much is the speed overhead? Creating Stream objects, calling 4 methods, creating temporary arrays (
{str1, str2, str3}
) look like much slower than a localif
or?:
, which the Java runtime can optimize. Is there some Stream-specific optimization injavac
and the Java runtime which makes it as fast as?:
? If not, I won't recommend this solution in performance-critical code. -
Aaron about 5 years@pts this is very likely to be slower than
?:
code and I'm sure you should avoid it in performance-critical code. It's however much more readable and you should recommend it in non-performance-critical code IMO, which I'm sure makes more than 99% of code. -
Holger about 5 years@pts There are no Stream specific optimizations, neither in
javac
nor in the runtime. This does not preclude the general optimizations, like inlining all of the code, followed by eliminating redundant operations. In principle, the end result could be as efficient as the plain conditional expressions, however, it’s rather unlikely that it ever gets there, as the runtime would spend the necessary effort only on the hottest code paths. -
Tom Anderson about 5 yearsFWIW, in SQL, this function is called coalesce, so i call it that in my code too. Whether that works for you depends how much you like SQL, really.
-
Cubic about 5 yearsThis is a huge pain to parse for anyone who isn't reading nested ternary operators every day.
-
Ravindra Ranwala about 5 years@pts The creation and reclamation of small objects whose constructors do little explicit work is cheap, especially on modern JVM implementations. Creating additional objects to enhance the clarity, simplicity, or power of a program is generally a good thing. There's a deep truth about optimization: it is easy to do more harm than good, especially if you optimize prematurely. So unless your application is performance stringent, you can use this approach with out any hesitation.
-
Todd Sewell about 5 yearsIf you're going to put it in a utility method you might as well make it efficient.
-
danielp about 5 yearsGreat solution! To increase readability a little bit I would suggest to add
str4
to the parameters ofStream.of(...)
and useorElse(null)
in the end. -
Peter Cordes about 5 years@Cubic: If you think it's hard to parse, write a comment like
// take first non-null of str1..3
. Once you know what it does, it becomes easy to see how. -
walen about 5 years@GustavoSilva Todd probably means that, this being a utility method of mine, there's no point in using
Arrays.stream()
when I can do the same with afor
and a!= null
, which is more efficient. And Todd would be right. However, when I coded this method I was looking for a way of doing this using Java 8 features, just like OP, so there's that. -
displayName about 5 yearsYou have omitted
s4
(orstr4
), which is to supposed be assigned tos
in the end, even if it is null. -
Bill K about 5 years@displayName I prefer to never use auto-formatting. It's impossible to teach an editor how to align things like this, much better to do it yourself.
-
Todd Sewell about 5 years@GustavoSilva Yeah that's basically it: if you're going to be putting this is a util function concerns about clean code aren't that important anymore, and so you might as well use a faster version.
-
cmaster - reinstate monica about 5 years@Cubic Yet, this is a simple repeated pattern. Once you parsed line 2, you've parsed the entire thing, no matter how many cases are included. And once you are done, you've learned to express a similar selection of ten different cases in a brief, and relatively simple manner. The next time you'll see a
?:
ladder, you'll know what it does. (Btw, functional programmers know this as(cond ...)
clauses: It's always a guard followed by the appropriate value to use when the guard is true.) -
tobias_k about 5 yearsWhy the extra
v0
parameter? -
tobias_k about 5 years@nullpointer Or
orElseNull
, which amounts to the same ifstr4
is null. -
Nick about 5 years@tobias_k The extra parameter when using varargs is the idiomatic way in Java to require 1 or more arguments rather than 0 or more. (See item 53 of Effective Java, Ed. 3., which uses
min
as an example.) I am less convinced that this is appropriate here. -
tobias_k about 5 years@Nick Yes, I guessed as much, but the function would work just as well (in fact behave exactly the same) without it.
-
Michael Anderson about 5 yearsOne of the key reasons for passing an extra first argument is to be explicit about the behaviour when passed an array. In this case, I want
firstNonNull(arr)
to return arr if it is not null. If it wasfirstNonNull(T... vs)
it would instead return the first non-null entry in arr. -
Vishwa Ratna about 5 yearshere findFirst() and findAny() will return the same, what if we have more than one not null;
-
Alvin Thompson about 5 yearsI guess I've been programming before jdk 8 came out for too long, but this doesn't seem any more readable to me. It's just different. It does have an advantage that the number of lines is (more or less) fixed regardless of the number of items to check.
-
Chauyan about 5 yearsPretty nice answer. Thanks for sharing