kni*_*ttl 10 java java-stream collectors java-16
JDK 16 现在toList()
直接在Stream
实例上包含一个方法。在以前的 Java 版本中,您总是必须使用该collect
方法并提供一个Collector
实例。
新方法显然需要输入更少的字符。这两种方法是否可以互换,或者是否存在应该注意的细微差别?
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());
Run Code Online (Sandbox Code Playgroud)
(这个问题类似于会不会 Stream.toList() 比 Collectors.toList() 表现更好,但关注行为而不是(仅)关注性能。)
Ban*_*zen 15
.collect(toList())
并且在创建的列表中元素的子类型兼容性方面toList()
表现不同。
看看以下替代方案:
List<Number> old = Stream.of(0).collect(Collectors.toList());
尽管我们将Integer流收集到Number列表中,但工作正常。List<Number> new = Stream.of(0).toList();
是等效的 Java 16+ 版本,但它无法编译(cannot convert from List<Integer> to List<Number>
;至少在 ecj(Eclipse Java 编译器)中)。至少有两种解决方法可以修复编译错误:
List<Number> fix1 = Stream.of(0).map(Number.class::cast).toList();
List<? extends Number> fix2 = Stream.of(0).toList();
据我了解,根本原因如下:Java 16 的泛型类型 TtoList()
与 Stream 本身的泛型类型 T 相同。然而,Collectors.toList() 的泛型类型 T 是从赋值的左侧传播的。如果这两种类型不同,您在替换所有旧调用时可能会看到错误。
Arv*_*ash 12
一个区别是,Stream.toList()
提供了一种List
即是不可改变的实现(类型ImmutableCollections.ListN
类似于由提供了可以不被添加到或排序)List.of()
和在对比的是可变的(可改变和排序)ArrayList
所提供Stream.collect(Collectors.toList())
。
演示:
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");
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
[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)
Run Code Online (Sandbox Code Playgroud)
请查看这篇文章了解更多详情。
有趣的是,成功Stream.toList()
返回了一个null
包含 s 的列表。
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);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
[null, null]
Run Code Online (Sandbox Code Playgroud)
另一方面,List.of(null, null)
抛出NullPointerException
.
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Object> list = List.of(null, null);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
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)
Run Code Online (Sandbox Code Playgroud)
注意:我使用openjdk-16-ea+34_osx-x64来编译和执行 Java SE 16 代码。
有用的资源:
Zhe*_*lov 12
这是一个小表格,总结了Stream.collect(Collectors.toList())
,Stream.collect(Collectors.toUnmodifiableList())
和之间的区别Stream.toList()
:
collect(toList())
:保证不可修改性 -否;允许空值 -是collect(toUnmodifiableList())
:保证不可修改性 -是;允许空值 -否toList()
:保证不可修改性 -是;允许空值 -是