Nulls in a Stream
Where a null actually blows up in a pipeline, and the cheapest place to remove it.
Open this lesson in the learning hubKey points
- A stream happily carries nulls. Nothing complains until an op dereferences one, far from where it came in.
filter(Objects::nonNull)as the first op is the cheapest fix, and it documents the intent.Collectors.toMapthrows on a null value;groupingBythrows on a null key.Stream.ofNullable(x)(Java 9+) gives an empty stream for null, soflatMapdeletes it.- Better still, stop producing the null: return an empty list or an
Optionalfrom the method above.
Example
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
List<String> raw = Arrays.asList("ada", null, "grace", null, "alan");
System.out.println("carries nulls : " + raw.stream().count());
System.out.println("cleaned : " + raw.stream().filter(Objects::nonNull).toList());
System.out.println("lengths : " + raw.stream().filter(Objects::nonNull)
.map(String::length).toList());
// Stream.ofNullable turns a null into an empty stream, so flatMap deletes it.
System.out.println("ofNullable : " + raw.stream().flatMap(Stream::ofNullable).toList());
// toMap explodes on a null VALUE, even when the key is perfectly fine.
try {
raw.stream().filter(Objects::nonNull)
.collect(Collectors.toMap(s -> s, s -> s.equals("grace") ? null : s));
} catch (NullPointerException e) {
System.out.println("toMap : NullPointerException, null value");
}
// groupingBy explodes on a null KEY instead.
try {
raw.stream().collect(Collectors.groupingBy(s -> s));
} catch (NullPointerException e) {
System.out.println("groupingBy : NullPointerException, null key");
}
// A map that does tolerate null values: build it yourself.
Map<String, String> lenient = new TreeMap<>();
raw.stream().filter(Objects::nonNull)
.forEach(s -> lenient.put(s, s.equals("grace") ? null : s));
System.out.println("lenient : " + lenient);
}
}
Drop nulls at the top of the pipeline, where the stack trace still points at the cause.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Streams course, and every lesson in it is listed on the Streams contents page.