Issue
JDK 16 now includes a toList()
method directly on Stream
instances. In previous Java versions, you always had to use the collect
method and provide a Collector
instance.
The new method is obviously fewer characters to type. Are both methods interchangeable or are there subtle differences one should be aware of?
var newList = someCollection.stream()
.map(x -> mapX(x))
.filter(x -> filterX(x))
.toList();
// vs.
var oldList = someCollection.stream()
.map(x -> mapX(x))
.filter(x -> filterX(x))
.collect(Collectors.toList());
(This question is similar to Would Stream.toList() perform better than Collectors.toList(), but focused on behavior and not (only) on performance.)
Solution
One difference is that 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())
.
Demo:
import java.util.stream.Stream;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = Stream.of("Hello").toList();
System.out.println(list);
list.add("Hi");
}
}
Output:
[Hello]
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:147)
at Main.main(Main.java:8)
Please check this article for more details.
Update:
Interestingly, Stream.toList()
returns a null
s-containing list successfully.
import java.util.stream.Stream;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Object> list = Stream.of(null, null).toList();
System.out.println(list);
}
}
Output:
[null, null]
On the other hand, List.of(null, null)
throws NullPointerException
.
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Object> list = List.of(null, null);
}
}
Output:
Exception in thread "main" java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Objects.java:208)
at java.base/java.util.ImmutableCollections$List12.<init>(ImmutableCollections.java:453)
at java.base/java.util.List.of(List.java:827)
at Main.main(Main.java:5)
Note: I've used openjdk-16-ea+34_osx-x64 to compile and execute the Java SE 16 code.
Useful resources:
Answered By - Arvind Kumar Avinash
Answer Checked By - David Goodson (JavaFixing Volunteer)