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.