43

What is the best/idiomatic way of doing a null check before getting a stream?

I have method that is receiving a List that might be null. So I can't just call .stream() on the passed in value. Is there some static helper in that would give me an empty stream if a value is null?

Stuart Marks
  • 120,620
  • 35
  • 192
  • 252
checketts
  • 12,991
  • 10
  • 50
  • 77
  • 2
    I heavily suggest to work on the list providing side. The whole purpose of optionals is to not deal with `null` references. If a method returns a list that could be `null`, it should return an optional instead. If that's not possible, you can wrap it into an optional (according to the answers). Additional, you want to do something with that list, i.e. you want to _consume_ it if it is present. So simply call [`Optional.ifPresent`](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#ifPresent-java.util.function.Consumer-) on it. – Seelenvirtuose Apr 02 '15 at 07:09

6 Answers6

74

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.

gdejohn
  • 7,162
  • 1
  • 31
  • 47
  • I like this example of a helper I could reuse a bunch and avoid having `Optional.orNullable` littered throughout my code. – checketts Apr 02 '15 at 06:59
  • 3
    There is no need for the explicit type parameter `` in `List::stream`; it works without. And `.orElse(Stream.empty())` may be replaced by `.orElseGet(Stream::empty)` which is slightly more efficient as it avoids constructing an empty stream. – Holger Apr 02 '15 at 10:17
  • @Holger, I made those changes, but I'm wondering what `Stream::empty` actually produces behind the scenes. An anonymous class? – gdejohn Apr 02 '15 at 11:05
  • 3
    See [“How will Java lambda functions be compiled?”](http://stackoverflow.com/q/16827262/2711488) and [“Does a lambda expression create an object on the heap every time it's executed?”](http://stackoverflow.com/q/27524445/2711488). Practically, there will be an instance of an anonymous class but it will be the same instance in every execution of the code (while `Stream.empty()` returns a new instance each time). – Holger Apr 02 '15 at 11:13
27

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

checketts
  • 12,991
  • 10
  • 50
  • 77
  • 4
    It's better to use `Collections::emptyList` instead of `ArrayList::new`. It makes the intent more clear and it's (slightly) more efficient. – Misha Apr 02 '15 at 06:43
17

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.)

Community
  • 1
  • 1
Stuart Marks
  • 120,620
  • 35
  • 192
  • 252
11

apache commons-collections4:

CollectionUtils.emptyIfNull(list).stream()
piotrek
  • 13,014
  • 10
  • 72
  • 156
  • Hi piotrek; your code might be correct, but it would be better with some context; for example, you could explain how and why this proposed change would resolve the questioner's problem, perhaps including a link to the relevant documentation. That would make it more useful to them, and also more useful to other site readers who are looking for solutions to similar problems. – Vince Bowdren Aug 17 '16 at 09:36
  • not sure what should be explained. apache commons-collections is one of the most standard java libraries. how it solves OP problem? it directly does what OP needs - it makes a stream from a nullable list – piotrek Aug 17 '16 at 17:09
5

Java 8:

Optional.ofNullable(list)
   .orElseGet(Collections::emptyList)
   .stream()

Java 9:

Stream.ofNullable(collection)
    .flatMap(Collection::stream)

Apache Commons Collections 4:

import org.apache.commons.collections4.CollectionUtils;

CollectionUtils.emptyIfNull(collection)
    .stream()
Michal Foksa
  • 9,725
  • 8
  • 43
  • 63
0

Personally I consider null deprecated and use Optional wherever possible despite the (tiny) performance overhead. So I use the interface from Stuart Marks with an implementation based on gdejohn, i.e.

@SuppressWarnings("unchecked")
static <T> Stream<T> nullableCollectionToStream(Collection<? extends T> coll)
{
    return (Stream<T>) Optional.ofNullable(coll)
                           .map(Collection::stream)
                           .orElseGet(Stream::empty);
}