1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        千萬(wàn)不要濫用Stream.toList(),有坑!

        共 8632字,需瀏覽 18分鐘

         ·

        2024-04-11 16:23

        往期熱門文章:

        
            

        1、強(qiáng)烈建議你不要再使用Date類了?。?!

        2、IDEA 接口調(diào)試神器,賊好用!

        3、Java內(nèi)部類有坑,100%內(nèi)存泄露!

        4、盤(pán)點(diǎn)Lombok的幾個(gè)騷操作

        5、被問(wèn)懵了,加密后的數(shù)據(jù)如何進(jìn)行模糊查詢?

        1.背景

        • 2.Stream toList()和 collect(Collectors.toList())的區(qū)別
          • Stream toList()
          • Stream collect(Collectors.toList())
        • 3.如何使用(不考慮性能)

        Stream toList()返回的是只讀List原則上不可修改,collect(Collectors.toList())默認(rèn)返回的是ArrayList,可以增刪改查

        1. 背景

        在公司看到開(kāi)發(fā)環(huán)境突然發(fā)現(xiàn)了UnsupportedOperationException 報(bào)錯(cuò),想到了不是自己throw的應(yīng)該就是操作collection不當(dāng)。
        發(fā)現(xiàn)的確是同事使用了類似stringList.stream().filter(number -> Long.parseLong(number) > 1).toList() 以stream.toList()作為返回, 后繼續(xù)使用了返回值做add操作,導(dǎo)致報(bào)錯(cuò)

        2. Stream toList()和 collect(Collectors.toList())的區(qū)別

        • JDK version: 21
        • IDE: IDEA
        從Java16開(kāi)始,Stream有了直接toList方法, java8時(shí)候常用的方法是 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調(diào)用的是Collections.unmodifiableList 而在unmodifiableList(List<? extends T> list)實(shí)現(xiàn)中,都會(huì)返回一個(gè)不可修改的List,所以不能使用set/add/remove等改變list數(shù)組的方法。
           
         return (list instanceof RandomAccess ?
                new UnmodifiableRandomAccessList<>(list) :
                new UnmodifiableList<>(list));
        圖片
        但其實(shí)也可以修改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));
        輸出結(jié)果是:
           
        WangWu

        ZhangSanWangWu

        Stream collect(Collectors.toList())

        返回一個(gè)ArrayList 如果沒(méi)有在toList()方法入?yún)⒅袀魅胫付⊿upplier的話, 可以做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. 關(guān)于 Unmodifiable Lists 說(shuō)明
        of和List.copyOf靜態(tài)工廠方法為創(chuàng)建不可修改的列表提供了一種方便的方法。這些方法創(chuàng)建的List實(shí)例具有以下特征:
        • 它們是不可修改的。元素不能被添加、刪除或替換。調(diào)用List上的任何mutator方法將始終導(dǎo)致引發(fā)UnsupportedOperationException。但是,如果包含的元素本身是可變的,這可能會(huì)導(dǎo)致List的內(nèi)容看起來(lái)發(fā)生變化。
        • 它們不允許空元素。嘗試使用空元素創(chuàng)建它們會(huì)導(dǎo)致NullPointerException。
        • 如果所有元素都是可序列化的,那么它們就是可序列化的。
        • 列表中元素的順序與提供的參數(shù)或提供的數(shù)組中元素的順序相同。列表及其子List視圖實(shí)現(xiàn)了RandomAccess接口。
        • 它們以價(jià)值為基礎(chǔ)。應(yīng)將相等的實(shí)例視為可互換的,不應(yīng)將它們用于同步,否則可能會(huì)發(fā)生不可預(yù)知的行為。如,在將來(lái)的版本中,同步可能會(huì)失敗。呼叫端不應(yīng)假設(shè)傳回執(zhí)行個(gè)體的識(shí)別。工廠可以自由地創(chuàng)建新的實(shí)例或重用現(xiàn)有的實(shí)例。
        • 它們將按照“序列化窗體”頁(yè)上的指定進(jìn)行序列化。
        • 該接口是Java集合框架的成員。

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

        確定其是一個(gè)不再被set/add/remove的list 可使用 Stream toList;
        如果使用collect(Collectors.toList()),sonar或idea自帶以及第三方的一些code checker會(huì)爆warning,以本人經(jīng)驗(yàn),可以使用collect(Collectors.toCollection(ArrayList::new))來(lái)代替
        來(lái)源:juejin.cn/post/7325717778597904420
            
        往期熱門文章:

        1、中國(guó)程序員獨(dú)立開(kāi)發(fā)9年、最受歡迎的開(kāi)源Redis客戶端,被Redis公司收購(gòu)了!
        2、我在代碼里面故意留個(gè)漏洞,違法嗎?
        3、一個(gè)現(xiàn)代化輕量級(jí)的跨平臺(tái) Redis 桌面客戶端,支持 Mac、Windows 和 Linux
        4、能用到“退休”的 600條 Linux 命令,可以解決日常99%的問(wèn)題~
        5、工作六年,看到這樣的代碼,內(nèi)心五味雜陳...
        6、拒絕寫(xiě)重復(fù)代碼,試試這套開(kāi)源的 SpringBoot 組件
        7、一次生產(chǎn)事故,來(lái)來(lái)回回搞了一個(gè)月,人麻了!
        8、面試官:Git 如何撤回已 Push 的代碼?問(wèn)倒一大片。。。
        9、SpringBoot 如何快速過(guò)濾出一次請(qǐng)求的所有日志?
        10、千萬(wàn)不要把 Request 傳遞到異步線程里面!有坑!
        10、別再用 offset 和 limit 分頁(yè)了,性能太差!

        瀏覽 38
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            欧美18一20男同69gay | 成人毛片片视频 | 嗯额宫交太长了高hhh | 大香蕉伊人免费在线观看 | 色婷婷五月天影院 | 国产一级a看免费视频 | 骚女久久 | 亚精品免费观看mV视频app | 殴美操逼视频;欧美操逼视频 | 亚洲国产另类无码 |