Java16的Stream.toList()和Stream.collect(Collectors.toList())的区别?

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());

(这个问题类似于会不会 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");
    }
}

输出:

[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包含 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);
    }
}

输出:

[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);
    }
}

输出:

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 代码。

有用的资源:

  1. JDK 错误# JDK-8180352
  2. 使用单个空参数调用 Java varargs 方法?
  • IIRC, `Collectors.toList()` is not guaranteed to give us a mutable list either. It just happens to do so in the Java versions we have seen so far.
  • It is not really a correct statement to say that `collect(toList())` returns a mutable list; the specification is very clear that it makes _no guarantees_ as to the mutability of the returned list. The current implementation _happens to_ return an `ArrayList` _right now_, but the spec was written explicitly to allow that to change. If you want a mutable list, use `toCollection(ArrayList::new)`.
  • @OleV.V. - Correct. The article linked in my answer mentions it as: `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.`

回答

这是一个小表格,总结了Stream.collect(Collectors.toList()),Stream.collect(Collectors.toUnmodifiableList())和之间的区别Stream.toList()

  • collect(toList()):保证不可修改性 -;允许空值 -
  • collect(toUnmodifiableList()):保证不可修改性 -;允许空值 -
  • toList():保证不可修改性 -;允许空值 -

以上是Java16的Stream.toList()和Stream.collect(Collectors.toList())的区别?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>