【问题标题】:Differences of Java 16's Stream.toList() and Stream.collect(Collectors.toList())?Java 16 的 Stream.toList() 和 Stream.collect(Collectors.toList()) 的区别?
【发布时间】:2021-05-04 06:49:55
【问题描述】:

JDK 16 now includes a toList() method directly on Stream instances。在以前的 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());

(这个问题类似于Would Stream.toList() perform better than Collectors.toList(),但关注的是行为而不是(仅)性能。)

【问题讨论】:

    标签: java java-stream collectors java-16


    【解决方案1】:

    一个区别是Stream.toList() 提供了一个不可变的List 实现(类型ImmutableCollections.ListN,不能添加或排序)类似于List.of() 提供的实现,与可变的(可以更改并排序)ArrayListStream.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)
    

    详情请查看this article

    更新:

    有趣的是,Stream.toList() 成功返回了一个包含nulls 的列表。

    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. Calling Java varargs method with single null argument?

    【讨论】:

    • IIRC, Collectors.toList() 也不保证给我们一个可变列表。在我们目前看到的 Java 版本中,它恰好是这样做的。
    • @OleV.V. - 正确的。我的答案中链接的文章将其提及为: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.
    • @Caramiriel List 接口有意设计了许多可选方法,即实现类不需要实现的方法和许多实现不实现的方法。你不是第一个想知道的人。
    • collect(toList()) 返回一个可变列表并不是一个正确的说法;规范非常清楚,它不保证返回列表的可变性。当前的实现碰巧返回一个ArrayList现在,但规范是明确编写的以允许更改。如果你想要一个可变列表,请使用toCollection(ArrayList::new)
    • 很遗憾List没有被分为ReadableListget()等和WritableListset()add()等,但是现在修复已经晚了. (注意:我最初来这里是为了建议 toCollection(ArrayList::new),当我需要一个可变列表时,我总是使用它,但是 The Man Himself 击败了我。?)
    【解决方案2】:

    这里有一张小表,总结了Stream.collect(Collectors.toList())Stream.collect(Collectors.toUnmodifiableList())Stream.toList()之间的区别:

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

    【讨论】:

    • 新方法 Stream.toList() 既不会产生不可修改的列表,也不会产生 collect(toUnmodifiableList()) 的快捷方式,因为 toUnmodifiableList() 不接受空值。Stream.toList() 的实现不受 Collector 接口的约束;因此, Stream.toList() 分配的内存更少。这使得在预先知道流大小时使用它是最佳选择。 blogs.oracle.com/javamagazine/hidden-gems-jdk16-jdk17-jep你能验证上述陈述吗
    猜你喜欢
    • 1970-01-01
    • 2021-04-20
    • 2015-10-31
    • 2017-09-25
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 2016-03-23
    • 2018-03-12
    相关资源
    最近更新 更多