<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>

          HashMap 中的一個(gè)“坑”!

          共 1024字,需瀏覽 3分鐘

           ·

          2021-11-07 04:34

          作者 | 王磊

          來(lái)源 | Java中文社群(ID:javacn666)

          轉(zhuǎn)載請(qǐng)聯(lián)系授權(quán)(微信ID:GG_Stone)

          最近公司新來(lái)了一個(gè)小伙伴,問(wèn)了磊哥一個(gè)比較“奇怪”的問(wèn)題,這個(gè)問(wèn)題本身的難度并不大,但比較“隱蔽”,那究竟是什么問(wèn)題呢?接下來(lái)我們一起來(lái)看。

          起因

          最近公司的系統(tǒng)要增加一個(gè)新的列表展示功能,功能本身難度并不大,但遇到了一個(gè)很“可怪”的問(wèn)題。小伙伴在執(zhí)行查詢列表時(shí),明明已經(jīng)使用了 order by 進(jìn)行排序了,但最終查詢出來(lái)的數(shù)據(jù)卻還是亂的。

          預(yù)期中的(正確)結(jié)果:現(xiàn)實(shí)中的(非預(yù)期)結(jié)果:那到底是哪里出現(xiàn)了問(wèn)題呢?

          問(wèn)題展示

          為了方便展示,我把復(fù)雜的業(yè)務(wù)程序簡(jiǎn)化成了以下代碼:

          import?java.util.HashMap;

          public?class?App?{

          ????public?static?void?main(String[]?args)?{
          ????????HashMap?result?=?getList();
          ????????result.forEach((k,?v)?->?{
          ????????????System.out.println(k?+?":"?+?v);
          ????????});
          ????}

          ????//?查詢方法(簡(jiǎn)化版)
          ????public?static?HashMap?getList()?{
          ????????HashMap?result?=?new?HashMap<>();?//?最終返回的結(jié)果集
          ????????//?偽代碼:從數(shù)據(jù)庫(kù)中查詢出了數(shù)據(jù),然后對(duì)數(shù)據(jù)進(jìn)行處理之后,存到了
          ????????for?(int?i?=?1;?i?<=?5;?i++)?{
          ????????????result.put("2022-10-"?+?i,?"hello?java"?+?i);
          ????????}
          ????????return?result;
          ????}
          }

          以上程序的執(zhí)行結(jié)果如下:

          預(yù)期的結(jié)果應(yīng)該是按時(shí)間的先后順序展示的,如下圖所示:

          PS:以上示例代碼中,插入元素的順序是有序的(從 1 到 5),相當(dāng)于實(shí)際業(yè)務(wù)場(chǎng)景中的 order by。

          原因分析

          既然原數(shù)據(jù)使用了 order by 排序,那么原數(shù)據(jù)肯定是沒問(wèn)題的,那問(wèn)題就只會(huì)出現(xiàn)在返回集 HashMap 上,然后我們?cè)侔呀裹c(diǎn)放到 HashMap 上, 瞬間醒悟,哦,原來(lái)如此。HashMap 使用的是哈希方式進(jìn)行存儲(chǔ)的,因此存入和讀取的順序可能是不一致的,這也說(shuō) HashMap 是無(wú)序的集合,所以會(huì)導(dǎo)致插入的(或 order by 的)順序,與最終展示的順序不一致。

          解決方案

          經(jīng)過(guò)上面的分析我們順利找到了問(wèn)題,那接下來(lái)就是制定相應(yīng)的解決方案了,我想到的解決方案有兩個(gè):

          1. 稍微麻煩一點(diǎn)但正確的解決方案:將返回的不確定數(shù)據(jù)類型 HashMap 改為確定的數(shù)據(jù)類型,比如 List
          2. 簡(jiǎn)單一點(diǎn)但并不是最優(yōu)的解決方案:將無(wú)序的 HashMap 改為有序的 LinkedHashMap,此方案的優(yōu)點(diǎn)是,只需要改動(dòng)一個(gè)單詞就可以解決整個(gè)問(wèn)題了。

          第一種解決方案大家都懂這里就不演示了,接下來(lái)咱們使用第二種解決方案將上面的問(wèn)題改造一下,最終的實(shí)現(xiàn)代碼如下:

          import?java.util.HashMap;
          import?java.util.LinkedHashMap;

          public?class?App?{

          ????public?static?void?main(String[]?args)?{
          ????????HashMap?result?=?getList();
          ????????result.forEach((k,?v)?->?{
          ????????????System.out.println(k?+?":"?+?v);
          ????????});
          ????}

          ????//?查詢方法(簡(jiǎn)化版)
          ????public?static?HashMap?getList()?{
          ????????HashMap?result?=?new?LinkedHashMap<>();?//?最終返回的結(jié)果集
          ????????//?偽代碼:從數(shù)據(jù)庫(kù)中查詢出了數(shù)據(jù),然后對(duì)數(shù)據(jù)進(jìn)行處理之后,存到了
          ????????for?(int?i?=?1;?i?<=?5;?i++)?{
          ????????????result.put("2022-10-"?+?i,?"hello?java"?+?i);
          ????????}
          ????????return?result;
          ????}
          }

          以上程序的執(zhí)行結(jié)果如下:從上述結(jié)果可以看出,當(dāng)使用 LinkedHashMap 替代了 HashMap ?之后,返回的順序就能和插入的順序保持一致了。

          LinkedHashMap 的魔力

          為什么 HashMap 是無(wú)序的,而 LinkedHashMap 卻是有序的呢?

          這要從二者的實(shí)現(xiàn)說(shuō)起了,LinkedHashMap 屬于 HashMap 的子類,所以 LinkedHashMap ?除了擁有 HashMap 的所有特性之后,還具備自身的一些擴(kuò)展屬性,其中就包括 LinkedHashMap 中額外維護(hù)了一個(gè)雙向鏈表,這個(gè)雙向鏈表就是用來(lái)保存元素的(插入)順序的,這也是為什么 LinkedHashMap 可以實(shí)現(xiàn)訪問(wèn)順序和插入順序一致的原因了。

          總結(jié)

          本文演示了 HashMap 作為返回類型時(shí)隱藏的一個(gè)小“坑”,因?yàn)?HashMap 本身是無(wú)序的,所以它會(huì)導(dǎo)致查詢順序和插入順序不一致的問(wèn)題,對(duì)應(yīng)的解決方案有兩種:使用確定的數(shù)據(jù)類型來(lái)替代 HashMap,比如 List,或者使用有序的 LinkedHashMap 來(lái)替代無(wú)序的 HashMap。

          關(guān)注公眾號(hào)「Java中文社群」查看更多 Java 總結(jié)性系列文章。


          往期推薦

          Java 中 List 分片的 5 種方法!


          阿里二面:為什么要分庫(kù)分表?


          50行代碼,搞定敏感數(shù)據(jù)讀寫!


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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  影音先锋男人资源网 | AV的天堂 | 亚洲高清无码免费在线观看 | w黄视频欧美精品韩日 | 操屄网站在线观看 |