Stream toList不能滥用以及与collect(Collectors.toList())的区别

这篇具有很好参考价值的文章主要介绍了Stream toList不能滥用以及与collect(Collectors.toList())的区别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Stream toList()返回的是只读List原则上不可修改,collect(Collectors.toList())默认返回的是ArrayList,可以增删改查

1. 背景

在公司看到开发环境突然发现了UnsupportedOperationException 报错,想到了不是自己throw的应该就是操作collection不当。
发现的确是同事使用了类似stringList.stream().filter(number -> Long.parseLong(number) > 1).toList() 以stream.toList()作为返回, 后继续使用了返回值做add操作,导致报错

2. Stream toList()和 collect(Collectors.toList())的区别

JDK version: 21

IDE: IDEA

从Java16开始,Stream有了直接toList方法, java8时候常用的方法是 stringList.stream().filter(number -> Long.parseLong(number) > 1).collect(Collectors.toList())

Stream toList()

    /**
     * Accumulates the elements of this stream into a {@code List}. The elements in
     * the list will be in this stream's encounter order, if one exists. The returned List
     * is unmodifiable; calls to any mutator method will always cause
     * {@code UnsupportedOperationException} to be thrown. There are no
     * guarantees on the implementation type or serializability of the returned List.
     *
     * <p>The returned instance may be <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
     * Callers should make no assumptions about the identity of the returned instances.
     * Identity-sensitive operations on these instances (reference equality ({@code ==}),
     * identity hash code, and synchronization) are unreliable and should be avoided.
     *
     * <p>This is a <a href="package-summary.html#StreamOps">terminal operation</a>.
     *
     * @apiNote If more control over the returned object is required, use
     * {@link Collectors#toCollection(Supplier)}.
     *
     * @implSpec The implementation in this interface returns a List produced as if by the following:
     * <pre>{@code
     * Collections.unmodifiableList(new ArrayList<>(Arrays.asList(this.toArray())))
     * }</pre>
     *
     * @implNote Most instances of Stream will override this method and provide an implementation
     * that is highly optimized compared to the implementation in this interface.
     *
     * @return a List containing the stream elements
     *
     * @since 16
     */
    @SuppressWarnings("unchecked")
    default List<T> toList() {
        return (List<T>) Collections.unmodifiableList(new ArrayList<>(Arrays.asList(this.toArray())));
    }

查看源码 Stream toList调用的是Collections.unmodifiableList 而在unmodifiableList(List<? extends T> list)实现中,都会返回一个不可修改的List,所以不能使用set/add/remove等改变list数组的方法

 return (list instanceof RandomAccess ?
                new UnmodifiableRandomAccessList<>(list) :
                new UnmodifiableList<>(list));

Stream toList不能滥用以及与collect(Collectors.toList())的区别,java


但其实也可以修改List的元素的某些属性,例如

        List<String> stringList = List.of("1", "2", "3");
        List<String> largeNumberList = stringList.stream().filter(number -> Long.parseLong(number) > 1).toList();
        List<String> largeNumberList2 = stringList.stream().filter(number -> Long.parseLong(number) > 1).collect(Collectors.toList());
//        largeNumberList.add("4"); //  java.lang.UnsupportedOperationException
        largeNumberList2.add("4"); //success

        // modify custom object attribute
        User userZhang = new User("ZhangSan");
        User userLi = new User("LiSi");
        List<User> userList = List.of(userZhang, userLi);
        List<User> filterList = userList.stream().filter(user -> "LiSi".equals(user.name)).toList();

        User first = filterList.getFirst();//java 21
        first.name = "WangWu";
        filterList.forEach(u -> System.out.println(u.name));
        //List.of返回的也是不能修改的List
        userList.forEach(u -> System.out.print(u.name));

输出结果是:

WangWu

ZhangSanWangWu

Stream collect(Collectors.toList())

返回一个ArrayList 如果没有在toList()方法入参中传入指定Supplier的话, 可以做ArrayList的任何操作

    /**
     * Returns a {@code Collector} that accumulates the input elements into a
     * new {@code List}. There are no guarantees on the type, mutability,
     * serializability, or thread-safety of the {@code List} returned; if more
     * control over the returned {@code List} is required, use {@link #toCollection(Supplier)}.
     *
     * @param <T> the type of the input elements
     * @return a {@code Collector} which collects all the input elements into a
     * {@code List}, in encounter order
     */
    public static <T>
    Collector<T, ?, List<T>> toList() {
        return new CollectorImpl<>(ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
    }

tips: List.of(),返回的也是不可修改的list, an unmodifiable list. 关于 Unmodifiable Lists 说明

The List.of and List.copyOf static factory methods provide a convenient way to create unmodifiable lists. The List instances created by these methods have the following characteristics:
They are unmodifiable. Elements cannot be added, removed, or replaced. Calling any mutator method on the List will always cause UnsupportedOperationException to be thrown. However, if the contained elements are themselves mutable, this may cause the List’s contents to appear to change.
They disallow null elements. Attempts to create them with null elements result in NullPointerException.
They are serializable if all elements are serializable.
The order of elements in the list is the same as the order of the provided arguments, or of the elements in the provided array.
The lists and their subList views implement the RandomAccess interface.
They are value-based. Programmers should treat instances that are equal as interchangeable and should not use them for synchronization, or unpredictable behavior may occur. For example, in a future release, synchronization may fail. Callers should make no assumptions about the identity of the returned instances. Factories are free to create new instances or reuse existing ones.
They are serialized as specified on the Serialized Form page.
This interface is a member of the Java Collections Framework.

3.如何使用(不考虑性能)

确定其是一个不再被set/add/remove的list 可使用 Stream toList;
如果使用collect(Collectors.toList()) ,sonar或idea自带以及第三方的一些code checker会爆warning, 以本人经验,可以使用collect(Collectors.toCollection(ArrayList::new))来代替文章来源地址https://www.toymoban.com/news/detail-814197.html

到了这里,关于Stream toList不能滥用以及与collect(Collectors.toList())的区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linq中.AsEnumerable(), AsQueryable() ,.ToList(),的区别和用法

    当使用LINQ查询数据时,我们常常会面临选择使用.AsEnumerable(), .AsQueryable(), 和 .ToList()方法的情况。这些方法在使用时有不同的效果和影响,需要根据具体场景来选择合适的方法 .AsEnumerable() 方法: 使用.AsEnumerable()方法可以将查询结果从数据库转换为IEnumerable 类型,从而在内存

    2024年02月08日
    浏览(27)
  • java8 Stream流Collectors.toMap当value为null时报空指针异常(NPE)

    一、问题 在项目测试过程中发现当使用下面这种方法后报空指针异常(NPE): 按理说 HashMap 的 key 和 value 都是可以为 null 的,不应该报 NPE 啊,经过定位分析发现 Map 中有个键值对的 value 为 null 值,在调用 Collectors.toMap 时报了 NullPointerException 。 二、分析 Collectors.toMap 的

    2024年02月15日
    浏览(43)
  • 聊聊Linq中.AsEnumerable(), AsQueryable() ,.ToList(),的区别和用法

    当使用LINQ查询数据时,我们常常会面临选择使用 .AsEnumerable() , .AsQueryable() , 和 .ToList() 方法的情况。这些方法在使用时有不同的效果和影响,需要根据具体场景来选择合适的方法。 .AsEnumerable() 方法: 使用 .AsEnumerable() 方法可以将查询结果从数据库转换为 IEnumerableT 类型,从而

    2024年02月15日
    浏览(34)
  • Java Stream 处理分组后取每组最大&Stream流之list转map、分组取每组第一条&Java 8 Collectors:reducing 示例(List分组取最值)

    有一个需求功能:先按照某一字段分组,再按照另外字段获取最大的那个 先根据appId分组,然后根据versionSort取最大. JDK1.8推出的stream流能极大的简化对集合的操作,让代码更美观,老规矩,直接上代码。 取list中对象的某个属性作为唯一key,对象作为value形成一个map集合,能

    2024年02月16日
    浏览(57)
  • stream流的collect出现空指针异常

    如果你的stream中存在null元素,而在使用collect方法时没有对null值进行处理,你可以使用过滤器方法(filter)来过滤掉null元素,或者使用Optional类来处理可能为null的元素。 以下是使用过滤器方法的示例代码: 这段代码将会过滤掉list中的null元素,然后将剩余的元素收集到一个

    2024年02月16日
    浏览(36)
  • 每日一道面试题之Collection 和 Collections 有什么区别?

    Collection和Collections是Java集合框架中的两个重要的概念,它们在Java集合框架中扮演不同的角色。 Collection 是 Java集合框架中的一个接口 ,它是 所有集合类的根接口 , 用于操作和管理一组对象 ,Collection接口的常见实现类包括 List、Set和Queue 等,分别定义了不同的存储方式。

    2024年02月16日
    浏览(38)
  • Java中Collection与Collections有什么区别?Java常见面试题解析

    本文将为大家详细讲解Java中Collection与Collections的区别点,这是我们进行开发时经常用到的知识点,也是大家在学习Java中很重要的一个知识点,更是我们在面试时有可能会问到的问题! 文章较长,干货满满,建议大家收藏慢慢学习。文末有本文重点总结,主页有全系列文章分

    2024年02月06日
    浏览(32)
  • Mybatis中 collection 和 association 标签 的区别

    collection 和 association 是 MyBatis 中用于定义映射关系的标签,它们的区别如下: 目标对象类型: collection 用于表示集合属性,即一个属性对应多个关联对象。 association 用于表示关联属性,即一个属性对应一个关联对象。 关联关系处理: collection 用于处理一对多或多对多的关联

    2024年02月09日
    浏览(45)
  • 【Collection集合】概述、使用以及常用方法

    1.Collection集合的概述 它是单列集合的顶级接口,它表示一组对象,这些对象也称为Collection的元素 JDK不提供此接口的任何直接实现,它提供更具体地子接口(如set和list)实现 2.创建Collection集合的对象 多态的方式 具体的实现类ArrayList,在java.util包下需要导包 向集合里添加元

    2024年02月08日
    浏览(39)
  • 【JAVA学习笔记】 56 - 开发中如何选择集合实现类,以及Collection工具类

    https://github.com/yinhai1114/Java_Learning_Code/blob/main/IDEA_Chapter14/src/com/yinhai/Collections_.java 目录 项目代码 Collections工具类 一、Collections工具类介绍 1.排序操作: (均为static方法) 2.查找、替换 在开发中,选择什么集合实现类,主要取决于业务操作特点,然后根据集合实现类特性进行 选择

    2024年02月06日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包