How to best create a Java 8 stream from a nullable object?
The best thing I can think of would be to use an Optional
with the orElseGet
method.
return Optional.ofNullable(userList)
.orElseGet(Collections::emptyList)
.stream()
.map(user -> user.getName())
.collect(toList());
Updated with @Misha's suggest to use Collections::emptyList
over ArrayList::new
I agree with Stuart Marks that list == null ? Stream.empty() : list.stream()
is the right way to do this (see his answer), or at least the right way to do this pre-Java 9 (see edit below), but I'll leave this answer up to demonstrate usage of the Optional API.
<T> Stream<T> getStream(List<T> list) {
return Optional.ofNullable(list).map(List::stream).orElseGet(Stream::empty);
}
Edit: Java 9 added the static factory method Stream.<T>ofNullable(T)
, which returns the empty stream given a null
argument, otherwise a stream with the argument as its only element. If the argument is a collection, we can then flatMap
to turn it into a stream.
<T> Stream<T> fromNullableCollection(Collection<? extends T> collection) {
return Stream.ofNullable(collection).flatMap(Collection::stream);
}
This doesn't misuse the Optional API as discussed by Stuart Marks, and in contrast to the ternary operator solution, there's no opportunity for a null pointer exception (like if you weren't paying attention and screwed up the order of the operands). It also works with an upper-bounded wildcard without needing SuppressWarnings("unchecked")
thanks to the signature of flatMap
, so you can get a Stream<T>
from a collection of elements of any subtype of T
.
In the other answers, the Optional
instance is created and used strictly within the same statement. The Optional
class is primarily useful for communicating with the caller about presence or absence of a return value, fused with the actual value if present. Using it wholly within a single method seems unnecessary.
Let me propose the following more prosaic technique:
static <T> Stream<T> nullableListToStream(List<T> list) {
return list == null ? Stream.empty() : list.stream();
}
I guess the ternary operator is somewhat déclassé these days, but I think this is the simplest and most efficient of the solutions.
If I were writing this for real (that is, for a real library, not just sample code on Stack Overflow) I'd put in wildcards so that that the stream return type can vary from the List type. Oh, and it can be a Collection, since that's where the stream()
method is defined:
@SuppressWarnings("unchecked")
static <T> Stream<T> nullableCollectionToStream(Collection<? extends T> coll) {
return coll == null ? Stream.empty() : (Stream<T>)coll.stream();
}
(The warning suppression is necessary because of the cast from Stream<? extends T>
to Stream<T>
which is safe, but the compiler doesn't know that.)