Can Java's Stream.collect() return null?
Collector.toList()
will return an empty List for you.
Here is the implementation:
public static <T>
Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}
As you can see ArrayList::new
is being used as a container for your items.
From JavaDoc of Collector:
A mutable reduction operation that accumulates input elements into a mutable result container, optionally transforming the accumulated result into a final representation after all input elements have been processed. Reduction operations can be performed either sequentially or in parallel.
A Collector is specified by four functions that work together to accumulate entries into a mutable result container, and optionally perform a final transform on the result. They are:
creation of a new result container (supplier())
incorporating a new data element into a result container (accumulator())
- combining two result containers into one (combiner())
- performing an optional final transform on the container (finisher())
And
A sequential implementation of a reduction using a collector would create a single result container using the supplier function, and invoke the accumulator function once for each input element. A parallel implementation would partition the input, create a result container for each partition, accumulate the contents of each partition into a subresult for that partition, and then use the combiner function to merge the subresults into a combined result.
So as long as you don't do weird things like combine function return null
, the Collector
always return at least a mutable container
using your provided supplier
function.
And I think it's very counter-intuitive if an implementation would ever return null
container.
This is not dependent on Stream.collect
, but on the individual Collector
. Collectors.toList()
will return an empty ArrayList
.
That said, there's no reason someone couldn't use a weird Collector
to return null in certain circumstances:
.collect(
Collector.of(
ArrayList::new,
ArrayList::add,
(a, b) -> {
a.addAll(b);
return a;
},
a -> a.isEmpty() ? null : a // finisher replaces empty list with null
)
);
So the Collector
is the thing you need to remember to check. I believe all of the Collectors
available out-of-the-box will return empty collections, as you'd expect.
I think this part of the documentation says that it cannot be null:
Returns a Collector that accumulates the input elements into a new List.
Highlights added by me. I think this new List means that something that isn't null.
I started to check ReferencePipeline.collect()
to check whether it's true for the actual implementation. Unfortunately, it was a futile attempt. There are so many cases here, like is it parallel? is it after a forEach
? etc.