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>

        Java 8 中 Map 騷操作,好用

        共 8356字,需瀏覽 17分鐘

         ·

        2022-07-05 18:00

        作者:lq木頭

        鏈接:https://juejin.cn/post/6844903958280945677

        Java 8 最大的特性無(wú)異于更多地面向函數(shù),比如引入了 lambda等,可以更好地進(jìn)行函數(shù)式編程。前段時(shí)間無(wú)意間發(fā)現(xiàn)了 map.merge() 方法,感覺(jué)還是很好用的,此文簡(jiǎn)單做一些相關(guān)介紹。首先我們先看一個(gè)例子。

        merge() 怎么用?

        假設(shè)我們有這么一段業(yè)務(wù)邏輯,我有一個(gè)學(xué)生成績(jī)對(duì)象的列表,對(duì)象包含學(xué)生姓名、科目、科目分?jǐn)?shù)三個(gè)屬性,要求求得每個(gè)學(xué)生的總成績(jī)。加入列表如下:

        private List<StudentScore> buildATestList() {
            List<StudentScore> studentScoreList = new ArrayList<>();
            StudentScore studentScore1 = new StudentScore() {{
                setStuName("張三");
                setSubject("語(yǔ)文");
                setScore(70);
            }};
            StudentScore studentScore2 = new StudentScore() {{
                setStuName("張三");
                setSubject("數(shù)學(xué)");
                setScore(80);
            }};
            StudentScore studentScore3 = new StudentScore() {{
                setStuName("張三");
                setSubject("英語(yǔ)");
                setScore(65);
            }};
            StudentScore studentScore4 = new StudentScore() {{
                setStuName("李四");
                setSubject("語(yǔ)文");
                setScore(68);
            }};
            StudentScore studentScore5 = new StudentScore() {{
                setStuName("李四");
                setSubject("數(shù)學(xué)");
                setScore(70);
            }};
            StudentScore studentScore6 = new StudentScore() {{
                setStuName("李四");
                setSubject("英語(yǔ)");
                setScore(90);
            }};
            StudentScore studentScore7 = new StudentScore() {{
                setStuName("王五");
                setSubject("語(yǔ)文");
                setScore(80);
            }};
            StudentScore studentScore8 = new StudentScore() {{
                setStuName("王五");
                setSubject("數(shù)學(xué)");
                setScore(85);
            }};
            StudentScore studentScore9 = new StudentScore() {{
                setStuName("王五");
                setSubject("英語(yǔ)");
                setScore(70);
            }};

            studentScoreList.add(studentScore1);
            studentScoreList.add(studentScore2);
            studentScoreList.add(studentScore3);
            studentScoreList.add(studentScore4);
            studentScoreList.add(studentScore5);
            studentScoreList.add(studentScore6);
            studentScoreList.add(studentScore7);
            studentScoreList.add(studentScore8);
            studentScoreList.add(studentScore9);

            return studentScoreList;
        }

        我們先看一下常規(guī)做法

        ObjectMapper objectMapper = new ObjectMapper();
        List<StudentScore> studentScoreList = buildATestList();

        Map<String, Integer> studentScoreMap = new HashMap<>();
        studentScoreList.forEach(studentScore -> {
            if (studentScoreMap.containsKey(studentScore.getStuName())) {
                studentScoreMap.put(studentScore.getStuName(), 
                                    studentScoreMap.get(studentScore.getStuName()) + studentScore.getScore());
            } else {
                studentScoreMap.put(studentScore.getStuName(), studentScore.getScore());
            }
        });

        System.out.println(objectMapper.writeValueAsString(studentScoreMap));

        // 結(jié)果如下:
        // {"李四":228,"張三":215,"王五":235}

        然后再看一下 merge() 是怎么做的:

        Map<String, Integer> studentScoreMap2 = new HashMap<>();
        studentScoreList.forEach(studentScore -> studentScoreMap2.merge(
          studentScore.getStuName(),
          studentScore.getScore(),
          Integer::sum));

        System.out.println(objectMapper.writeValueAsString(studentScoreMap2));

        // 結(jié)果如下:
        // {"李四":228,"張三":215,"王五":235}

        merge() 簡(jiǎn)介

        merge() 可以這么理解:它將新的值賦值到 key (如果不存在)或更新給定的key 值對(duì)應(yīng)的 value,其源碼如下:

        default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
            Objects.requireNonNull(remappingFunction);
            Objects.requireNonNull(value);
            V oldValue = this.get(key);
            V newValue = oldValue == null ? value : remappingFunction.apply(oldValue, value);
            if (newValue == null) {
                this.remove(key);
            } else {
                this.put(key, newValue);
            }

            return newValue;
        }

        我們可以看到原理也是很簡(jiǎn)單的,該方法接收三個(gè)參數(shù),一個(gè) key 值,一個(gè) value,一個(gè) remappingFunction ,如果給定的key不存在,它就變成了 put(key, value) 。

        但是,如果 key 已經(jīng)存在一些值,我們  remappingFunction 可以選擇合并的方式,然后將合并得到的 newValue 賦值給原先的 key。

        使用場(chǎng)景

        這個(gè)使用場(chǎng)景相對(duì)來(lái)說(shuō)還是比較多的,比如分組求和這類(lèi)的操作,雖然 stream 中有相關(guān) groupingBy() 方法,但如果你想在循環(huán)中做一些其他操作的時(shí)候,merge() 還是一個(gè)挺不錯(cuò)的選擇的。

        其他

        除了 merge() 方法之外,我還看到了一些Java 8 中 map 相關(guān)的其他方法,比如 putIfAbsent 、compute() 、computeIfAbsent() 、computeIfPresent,這些方法我們看名字應(yīng)該就知道是什么意思了,故此處就不做過(guò)多介紹了,感興趣的可以簡(jiǎn)單閱讀一下源碼(都還是挺易懂的),這里我們貼一下 compute()(Map.class) 的源碼,其返回值是計(jì)算后得到的新值:

        default V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
            Objects.requireNonNull(remappingFunction);
            V oldValue = this.get(key);
            V newValue = remappingFunction.apply(key, oldValue);
            if (newValue == null) {
                if (oldValue == null && !this.containsKey(key)) {
                    return null;
                } else {
                    this.remove(key);
                    return null;
                }
            } else {
                this.put(key, newValue);
                return newValue;
            }
        }

        總結(jié)

        本文簡(jiǎn)單介紹了一下 Map.merge() 的方法,除此之外,Java 8 中的 HashMap 實(shí)現(xiàn)方法使用了 TreeNode 和 紅黑樹(shù),在源碼閱讀上可能有一點(diǎn)難度,不過(guò)原理上還是相似的,compute() 同理。所以,源碼肯定是要看的,不懂的地方多讀多練自然就理解了。

        END


        關(guān)注 Stephen,一起學(xué)習(xí),一起成長(zhǎng)。


        點(diǎn)“在看”支持下吧


        點(diǎn) 閱讀原文 可優(yōu)惠充值話(huà)費(fèi),流量,視頻會(huì)員等。

        瀏覽 39
        點(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>
            亚洲第一国产 黄AV动漫软件 | 男女色情18岁网站在线观看 | 欧美成人午夜一区二区三区 | 婷婷色播基地 | 中年风韵犹存裸体妇女 | 国产精品午夜一区二区三区视频 | 农村嫩苞一区二区三区在线观看 | 国产精品欧美一区二区三区奶水 | 女人帮男人橹视频播放 | 色视频在线播放 |