79

I am looking for method that can make stream of collection, but is null safe. If collection is null, empty stream is returned. Like this:

Utils.nullSafeStream(collection).filter(...);

I have created my own method:

public static <T> Stream<T> nullSafeStream(Collection<T> collection) {
    if (collection == null) {
        return Stream.empty();
    }
    return collection.stream();
}

But I am curious, if there is something like this in standard JDK?

Gondy
  • 4,925
  • 4
  • 40
  • 46
  • 8
    You should try to avoid the `null` collection in the first place. The best practice is to prefer using an empty collection instead. – Didier L Jan 11 '17 at 12:16
  • 4
    Yes, I agree, but if you depend on someone's else library you don't have choice. – Gondy Mar 20 '17 at 18:31
  • In that case you could simply replace the collection you receive from that library by an empty one when it returns `null`. A bit like in greg's solution. – Didier L Mar 22 '17 at 21:48

6 Answers6

107

You could use Optional :

Optional.ofNullable(collection).orElse(Collections.emptySet()).stream()...

I chose Collections.emptySet() arbitrarily as the default value in case collection is null. This will result in the stream() method call producing an empty Stream if collection is null.

Example :

Collection<Integer> collection = Arrays.asList (1,2,3);
System.out.println (Optional.ofNullable(collection).orElse(Collections.emptySet()).stream().count ());
collection = null;
System.out.println (Optional.ofNullable(collection).orElse(Collections.emptySet()).stream().count ());

Output:

3
0

Alternately, as marstran suggested, you can use:

Optional.ofNullable(collection).map(Collection::stream).orElse(Stream.empty ())...
Eran
  • 387,369
  • 54
  • 702
  • 768
  • 7
    `Optional.ofNullable(collection).map(Collection::stream).orElse(Stream.empty());` is a possible equivalent solution where you don't have to choose `Collections.emptySet()`. – marstran Jan 11 '17 at 11:59
  • 6
    As mentioned by [@StuartMarks](http://stackoverflow.com/users/1441122/stuart-marks) as _Use, Abstruse Use, and Abuse_: [Rule #4](https://youtu.be/Ej0sss6cq14?t=27m51s): _It's generally a bad idea to create an `Optional` for the sole purpose of chaining methods from it to get a value_. – Didier L Jan 11 '17 at 13:04
  • @DidierL I can't watch that youtube clip right now, but my first impression is that I, in general, disagree. I will check it out later today. The case we have here looks quite clean with `collection != null ? collections.stream() : Stream.empty();` though. – marstran Jan 11 '17 at 13:37
  • 4
    @marstran The point of Stuart Marks is that, in general, it will be more readable not to use an optional (outside the fact that it avoids some boxing and outboxing). Of course this remains a guideline. – Didier L Jan 11 '17 at 16:50
  • 1
    I think it depends on the chain. If it is a chain to only check for null for the reference passed in, it's probably overkill. But chaining with Optional is useful if you are diving down two or more levels of the object graph and checking null every step of the way to harvest a value. At that point you are squashing down a bunch of nested conditional statements. At this point, IMHO, Optional chaining is cleaner and easier to read. – 8bitjunkie Mar 20 '18 at 12:24
  • @Eran how would you write a Junit for this? – mitali Nov 10 '21 at 00:58
73

You can use org.apache.commons.collections4.CollectionUtils::emptyIfNull function:

import static org.apache.commons.collections4.CollectionUtils.emptyIfNull;
      
emptyIfNull(list).stream()
                 .filter(...);
Gondy
  • 4,925
  • 4
  • 40
  • 46
greg
  • 1,070
  • 7
  • 4
  • 2
    I actually like this solution, because is very simple. However, External library is required, but in the world of Maven and Gradle it's not a problem. I know I was asking for JDK8 but apparently nothing this simple is there. – Gondy Mar 28 '17 at 13:19
  • 1
    Can't use `orElse` or `orElseThrow` with this, but `Optional.ofNullable()` offers both these methods. – Farrukh Chishti Feb 26 '19 at 07:14
  • 1
    Depends on the requirement. But if you actually just want an emptyCollection in your .orElse() call, I find this a lot nicer to read. – Tobias Grunwald Oct 30 '20 at 15:10
51

Not sure if helps, but since Java 9, you can just write:

Stream.ofNullable(nullableCollection)
      .flatMap(Collection::stream)
fhiegel
  • 631
  • 6
  • 12
9

Your collectionAsStream() method can be simplified to a version even simpler than when using Optional:

public static <T> Stream<T> collectionAsStream(Collection<T> collection) {
    return collection == null ? Stream.empty() : collection.stream();
}

Note that in most cases, it's probably better to just test for nullness before building the stream pipeline:

if (collection != null) {
    collection.stream().filter(...)
} // else do nothing

What you want seems to be only useful when you need to return the stream (including for flatmapping), or maybe concatenate it with another one.

Didier L
  • 18,905
  • 10
  • 61
  • 103
8

You can use something like that:

public static void main(String [] args) {
    List<String> someList = new ArrayList<>();
    asStream(someList).forEach(System.out::println);
}

public static <T> Stream<T> asStream(final Collection<T> collection) {
    return Optional.ofNullable(collection)
            .map(Collection::stream)
            .orElseGet(Stream::empty);
}
g-t
  • 1,455
  • 12
  • 17
7

If downloading the library org.apache.commons.collections4 is not an option, you can just write your own wrapper/convenience method.

public static <T> Stream<T> asStream(final Collection<T> collection) {
    return collection == null ? ( Stream<T> ) Collections.emptyList().stream() 
                              : collection.stream();
}

Or wrapping the collection with Optional.ofNullable

public static <T> Stream<T> asStream(final Collection<T> collection) {
    return Optional.ofNullable(collection)
            .orElse( Collections.emptySet()).stream();
}
alltej
  • 6,787
  • 10
  • 46
  • 87