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>

        lambda表達式知識點補充

        共 6539字,需瀏覽 14分鐘

         ·

        2021-08-14 08:51

        前言

        截止到昨天,我們已經(jīng)分享完了spring cloud的核心模塊的相關(guān)知識點,下一步的想法是繼續(xù)深挖spring相關(guān)的知識點,或者開始分享dubbo的知識點,或者分享Netty的相關(guān)知識點。

        單從目前我對以上知識的掌握來看,分享前兩種知識點的可能性比較大,但是后一種我覺得還有很有難度的,因為我對netty的積累還不夠,所以暫時可能不會分享。目前我比較傾向于dubbo相關(guān)知識點的分享,主要有兩個原因,一個是對于dubbo我的知識盲區(qū)點比較多,系統(tǒng)地學(xué)習一下dubbo剛好可以查漏補缺;另一個就是最近一直在分享spring相關(guān)知識點,有點上頭,所以暫時換個頻道。

        好了,關(guān)于未來幾天的內(nèi)容分享計劃,我們暫時就先說這么多,下面插播一期lambda相關(guān)的知識點。

        lambda表達式

        關(guān)于lambda表達式,我們之前也有分享過幾期內(nèi)容,但由于這一塊的知識比較零散,而且內(nèi)容比較多,很難一次分享完,所以今天我們在原來分享的基礎(chǔ)上,再來做一些補充,下面我們直接開始吧。

        parallelStream

        可能很多小伙伴只知道stream,并不知道parallelStream,其實,我以前也只知道steam,后來有一次和一個同事討論一個技術(shù)問題,他推薦我使用parallelStream。當然,當時只管著用,就沒有仔細研究過,知道最近遇到了一個問題,我才真正去查了一些資料,了解了parallelStream的相關(guān)知識點。

        parallelStream中文含義并發(fā)流、平行流,和stream相比,它效率更高,內(nèi)部采用了 fork/join機制,即把一個大任務(wù)拆分(fork)成多個子任務(wù),子任務(wù)之間還會繼續(xù)拆分,然后以多線程的方式去運行,最后運行結(jié)束后,將子任務(wù)結(jié)果進行整合(join),生成最后的運行結(jié)果,整體運行流程大致如下:

        下面是一段示例代碼,在代碼中我們先初始化了一個長度為10000List,然后分別通過普通的streamparallelStream分別遍歷integers,然后把其中的值轉(zhuǎn)換成string類型,放入一個新的集合中,這里用了map(String::valueOf),最后分別打印他們的運行時間,比較他們的性能

         private static void parallelStreamTest2() {
                List<Integer> integers = Lists.newArrayList();
                Random random = new Random(100);
                for (int i = 0; i < 10000; i++) {
                    integers.add(random.nextInt(100));
                }
                long start = System.currentTimeMillis();
                List<String> collect1 = integers.parallelStream().map(String::valueOf).collect(Collectors.toList());
                System.out.println("collect1 用時:" + (System.currentTimeMillis() - start));
                long start2 = System.currentTimeMillis();
                List<String> collect2 = integers.stream().map(String::valueOf).collect(Collectors.toList());
                System.out.println("collect2 用時:" + (System.currentTimeMillis() - start2));
                System.out.println("collect1: " + collect1);
                System.out.println("collect2: " + collect2);
            }

        運行結(jié)果如下:

        根據(jù)本次示例運行結(jié)果,我們可以發(fā)現(xiàn)parallelStream比普通的stream快了32倍,這數(shù)據(jù)就足以說明parallelStreamstream性能要好,當然具體的數(shù)據(jù)還是取決于你的電腦性能。

        但是需要注意的是,由于parallelStream是多個子任務(wù)同時運行的,所以它本身是線程不安全的,而stream是串行運行所以線程是安全的。下面我們通過一段代碼來說明parallelStream的線程安全問題:

        private static void parallelStreamTest() {
            List<Integer> integers = Lists.newArrayList();
            Random random = new Random(100);
            for (int i = 0; i < 10000; i++) {
                integers.add(random.nextInt(100));
            }
            AtomicInteger index = new AtomicInteger(0);
            List<Integer> integersList = Lists.newArrayList();
            System.out.println("原始數(shù)據(jù):" + integers.size());
            integers.stream().forEach(i -> {
            // integers.parallelStream().forEach(i -> {
                index.incrementAndGet();
                integersList.add(i);
            });
            System.out.println("處理完成后:integerList.size:" + integersList.size());

         }

        同樣的代碼,如果用stream(),返回結(jié)果就是正常的:

        但如果用parallelStream,這結(jié)果就有點離譜了,數(shù)據(jù)一半都被弄丟了:

        如果parallelStream內(nèi)部如果多加一行打印,結(jié)果會稍微好一點,但是也是有問題的:

        導(dǎo)致線程不安全問題的原因是因為我們parallelStream內(nèi)部用到了integersList這個共享變量,如果你的parallelStream內(nèi)部沒有寫相關(guān)的操作,那應(yīng)該是不存在線程安全問題的,總之,慎用parallelStream。

        另外還有一點需要注意,那就是parallelStream無法確保運行結(jié)果的有序性,雖然在本次運行結(jié)果中,它和stream的運行結(jié)果是一致的,但是在某些情況下,它的結(jié)果是無序的,如果你對順序有要求,那可能需要你自己重新排序。

        groupBy

        groupBy也算是一個比較常用的lambda表達式了,我們經(jīng)常用它來對List分組,然后生成一個Map,mapkey是我們分組的字段,value就是我們分組后的List,下面我們先通過一個實例簡單演示下:

        List<TestVo> testVoList = Lists.newArrayList();
        testVoList.add(new TestVo(1L1111L10L"test1"));
        testVoList.add(new TestVo(2L2111L20L"test2"));
        testVoList.add(new TestVo(3L3111L30L"test3"));

        testVoList.add(new TestVo(4L1112L10L"test4"));
        testVoList.add(new TestVo(5L2112L20L"test5"));
        testVoList.add(new TestVo(6L3112L30L"test6"));

        testVoList.add(new TestVo(7L1113L10L"test7"));
        testVoList.add(new TestVo(8L2113L20L"test8"));
        testVoList.add(new TestVo(9L3113L30L"test9"));
        testVoList.add(new TestVo(10L4113L40L"test10"));

        System.out.println("初始化后:testVoList = " + testVoList);

        Map<Long, List<TestVo>> typeIdTestVoMap = testVoList.stream().collect(Collectors.groupingBy(TestVo::getTypeId));
        System.out.println("typeIdTestVoMap = " + typeIdTestVoMap);


        public static class TestVo {
            Long id;
            Integer sort;
            Long projectNum;
            Long typeId;
            String name;
        }

        在上面的代碼中,我們先初始化了一個testVoList,然后先通過groupingByTypeId分組,最終結(jié)果如下:

        可以看到,最后生成的map就是以TypeIdkey進行分組的。

        下面的代碼是多字段分組的寫法:

        Map<String, List<TestVo>> projectNUmSortMap = testVoList.stream().collect(Collectors.groupingBy(t -> String.format("%s.%s", t.getProjectNum(), t.getSort())));
        System.out.println("projectNUmSortMap = " + projectNUmSortMap);

        運行結(jié)果如下:

        根據(jù)運行結(jié)果可以看出,我們的map已經(jīng)按ProjectNum.Sort的形式為我們分組了,我覺得這種方式最常用,特別是在復(fù)雜業(yè)務(wù)中,數(shù)據(jù)關(guān)系比較復(fù)雜的話,用這種方式可以很方便地構(gòu)建出我們需要的數(shù)據(jù)格式。

        總結(jié)

        lambda表達式用起來確實很方便,也確實很爽,使用它不僅可以讓我們的代碼更簡潔,而且還提升我們系統(tǒng)性能,當然,它也有一些弊端,比如不便于問題排查(解決方式也很簡單,增加一些必要的日志),但是我覺得只要你用好了lambda表達式,那它只會讓你受益無窮。好了,今天內(nèi)容就到這里吧,又是忙碌的一天,大家晚安!

        - END -


        瀏覽 49
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        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>
            日本护士肉体做爰 | 日本一二三区视频 | 二级片网站 | 精品欧美成人А∨无码视频黑料 | 免费成人高清视频 | 日本免费AAAAAAAA直播片 | 青青草手机视频在线 | 囯产精品久久欠久久久久久九秃大 | 韩国黄视频 | 2019中文字幕mv第三季歌词 |