<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java 8 中 Map 騷操作之 merge() 的用法

          共 3434字,需瀏覽 7分鐘

           ·

          2020-09-10 17:45

          點擊上方藍(lán)色“程序猿DD”,選擇“設(shè)為星標(biāo)”

          回復(fù)“資源”獲取獨家整理的學(xué)習(xí)資料!

          來源 |?juejin.im/post/5d9b455ae51d45782b0c1bfb

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

          merge()?怎么用?

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

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

          ????????Map?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?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()?簡介

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

          ????default?V?merge(K?key,?V?value,?BiFunctionsuper?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;
          ????}

          我們可以看到原理也是很簡單的,該方法接收三個參數(shù),一個 key 值,一個 value,一個?remappingFunction?,如果給定的key不存在,它就變成了?put(key, value)?。但是,如果 key 已經(jīng)存在一些值,我們 ?remappingFunction?可以選擇合并的方式,然后將合并得到的?newValue?賦值給原先的 key。

          使用場景

          這個使用場景相對來說還是比較多的,比如分組求和這類的操作,雖然 stream 中有相關(guān)?groupingBy()?方法,但如果你想在循環(huán)中做一些其他操作的時候,merge()?還是一個挺不錯的選擇的。

          其他

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

          ????default?V?compute(K?key,?BiFunctionsuper?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é)

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


          往期推薦

          程序員接私活完整攻略+贈開源管理系統(tǒng)

          記一次由Redis分布式鎖造成的重大事故,避免以后踩坑!

          三種 MySQL 大表優(yōu)化方案

          通過這個故事理解啥是 NIO

          重磅!GitHub 推出容器鏡像倉庫服務(wù)!

          Upwork 發(fā)布最賺錢的編程語言 Top 15


          我們在星球聊了很多深度話題,你不來看看?

          我的星球是否適合你?

          點擊閱讀原文看看我們都聊過啥?

          瀏覽 45
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本一道本视频一二三 | 国产剧情一区二区 | 在线免费观看日韩一级 | 91麻豆一区二区三区 | 亚洲午夜无码久久久A |