Stream#toList
Java 16 adds a method on the Stream
interface: toList()
. To quote the Javadoc:
The returned List
is unmodifiable; calls to any mutator method will always cause UnsupportedOperationException
to be thrown.
Not just more convenient than Collectors
, this method has some goodies like better performance on parallel streams.
In particular with parallel() -- as it avoids result copying.
Benchmark is a few simple ops on 100K elem stream of Long.
For a further reading please go to: http://marxsoftware.blogspot.com/2020/12/jdk16-stream-to-list.html
In resume the link states something like this.
Gotcha: It may be tempting to go into one's code base and use
stream.toList() as a drop-in replacement for
stream.collect(Collectors.toList()), but there may be differences in
behavior if the code has a direct or indirect dependency on the
implementation of stream.collect(Collectors.toList()) returning an
ArrayList. Some of the key differences between the List returned by
stream.collect(Collectors.toList()) and stream.toList() are spelled
out in the remainder of this post.
The Javadoc-based documentation for Collectors.toList() states
(emphasis added), "Returns a Collector that accumulates the input
elements into a new List. There are no guarantees on the type,
mutability, serializability, or thread-safety of the List returned..."
Although there are no guarantees regarding the "type, mutability,
serializability, or thread-safety" on the List provided by
Collectors.toList(), it is expected that some may have realized it's
currently an ArrayList and have used it in ways that depend on the
characteristics of an ArrayList
What i understand is that the Stream.toList() it will result in a inmutable List.
Stream.toList() provides a List implementation that is immutable (type
ImmutableCollections.ListN that cannot be added to or sorted) similar
to that provided by List.of() and in contrast to the mutable (can be
changed and sorted) ArrayList provided by
Stream.collect(Collectors.toList()). Any existing code depending on
the ability to mutate the ArrayList returned by
Stream.collect(Collectors.toList()) will not work with Stream.toList()
and an UnsupportedOperationException will be thrown.
Although the implementation nature of the Lists returned by
Stream.collect(Collectors.toList()) and Stream.toList() are very
different, they still both implement the List interface and so they
are considered equal when compared using List.equals(Object)
And this method will allow nulls so starting from Java 16 we will have a
mutable/null-friendly----->Collectors.toList()
immutable/null-friendly--->Stream.toList()
immutable/null-hostile---->Collectors.toUnmodifiableList() //Naughty
It's great.
List.of(Arrays.asList(1, 2, 3, 4).stream().toArray(Integer[]::new));
– Teasleylist -> (List<T>)List.of(list.toArray())
, obviously since you can't create a generic array, they have to cast.. – MegaeraStream.of(1, 2, 3, 4)
instead ofArrays.asList(1, 2, 3, 4).stream()
and, of course, in Java 9, you can do it even simpler by writingList.of(1, 2, 3, 4)
in the first place… – OverbiteArrays.asList(1, 2, 3, 4)
should be read as some list. – TeasleyCollectors.unmodifiableList()
in the first place? It guarantees that the list is unmodifiable. ButCollectors.toList()
already can be unmodifiable. So instead of continuing to say there's no guarantee withtoList
, why not maketoList
return an unmodifiable list and document it as such? – CockatricetoList
is not documented to return anything specific, it could in future return anArrayList
for example – MegaeratoList()
still returns a mutable list, likely raising the amount of code that wrongly relies on this property. But even iftoList()
now returned an immutable list, it was fundamentally different totoUnmodifiableList()
, as the former still doesn’t specify the type and properties of the returned list, while the latter makes specific guarantees which the user can rely on. Besides that, the list type returned bytoUnmodifiableList()
will be the same as withList.of(…)
, disallowingnull
, not only as element, but even as argument to query methods. – OverbitetoList()
returned a list type with such a special behavior. Being immutable is clearly within the things that a programmer should expect, throwing an NPE oncontains(null)
perhaps not. – Overbite