![](/img/trans.png)
[英]Would Stream.toList() perform better than Collectors.toList()
[英]Differences of Java 16's Stream.toList() and Stream.collect(Collectors.toList())?
JDK 16 現在直接在Stream
實例上包含一個toList()
方法。 在之前的 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());
(這個問題類似於會 Stream.toList() 比 Collectors.toList() 表現更好,但關注的是行為而不是(僅)性能。)
一個區別是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");
}
}
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)
請查看這篇文章了解更多詳情。
有趣的是, Stream.toList()
成功返回了一個包含null
的列表。
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]
另一方面, 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);
}
}
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)
注意:我使用openjdk-16-ea+34_osx-x64編譯並執行了Java SE 16代碼。
有用的資源:
Here is a small table that summarizes the differences between Stream.collect(Collectors.toList())
, Stream.collect(Collectors.toUnmodifiableList())
and Stream.toList()
:
collect(toList())
:保證不可修改性 -否; 允許空值 -是collect(toUnmodifiableList())
:保證不可修改性 -是的; 允許空值 -否toList()
:保證不可修改性 -是的; 允許空值 -是 .collect(toList())
和toList()
在創建的列表中元素的子類型兼容性方面表現不同。
看看以下替代方案:
List<Number> old = Stream.of(0).collect(Collectors.toList());
工作正常,盡管我們將 Integer 的stream收集到Number列表中。List<Number> new = Stream.of(0).toList();
是等效的 Java 16+ 版本,但它不能編譯( cannot convert from List<Integer> to List<Number>
;至少在 ecj 中,Eclipse ZD52387880E2EA223817A 編譯器)。至少有兩種解決方法可以修復編譯錯誤:
List<Number> fix1 = Stream.of(0).map(Number.class::cast).toList();
List<? extends Number> fix2 = Stream.of(0).toList();
List<? extends Number> fix2 = Stream.of(0).toList();
據我了解,根本原因如下:Java 16 toList()
的泛型 T 與 Stream 本身的泛型 T 相同。 但是,Collectors.toList() 的泛型類型 T 是從賦值的左側傳播的。 如果這兩種類型不同,則在替換所有舊調用時可能會看到錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.