<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 使用的時候指定容量?

          共 3579字,需瀏覽 8分鐘

           ·

          2022-11-29 12:20

          關(guān)注我們,設(shè)為星標(biāo),每天7:40不見不散,架構(gòu)路上與您共享

          回復(fù)架構(gòu)師獲取資源


          大家好,我是你們的朋友架構(gòu)君,一個會寫代碼吟詩的架構(gòu)師。

          'javajgs.com';


          原文:
          blog.csdn.net/qq_35387940/article/details/125682065


          前言


          其實(shí)可以看到我寫了這么久的博客,很少去寫hashMap的東西。

          為什么?因?yàn)檫@個東西感覺是java面試必備的,我感覺大家都看到膩了,所以一直沒怎么去寫hashMap相關(guān)的。

          ps:之前整理過一個hashmap存值的流程圖,感覺夠了,因?yàn)閜ut過程基本可以把所有核心點(diǎn)都過一遍。

          今天為什么我突然要來寫這一篇文章,因?yàn)樽罱诠究匆恍├享?xiàng)目代碼,我才發(fā)現(xiàn)原來其實(shí)很多人都沒用對。

          本篇內(nèi)容:

          • 舉例說明 HashMap 使用的時候指定容量 錯誤用法;
          • 源碼走讀,HashMap初始容量的 計(jì)算方式;
          • 源碼走讀擴(kuò)容的點(diǎn);
          • 正確應(yīng)該怎么去用,一定要理解再用;
          • 一些雜談。

          正文

          不開玩笑,真的都知道指定容量,但是有些用對了,有些沒用對。


          為什么要指定容量?


          這個原由,都不用說,阿里的java開發(fā)手冊就說的很明白:

          其實(shí)核心點(diǎn),就是避免數(shù)據(jù)量慢慢增加,導(dǎo)致反復(fù)觸發(fā)擴(kuò)容,影響性能。

          于是乎就很多錯誤的使用方式了(雖熱影響不大):

          錯誤理解使用示例 ① :

          分頁查詢出來的數(shù)據(jù),需要轉(zhuǎn)換成 Map, 因?yàn)榉猪撌枪潭艘豁撟疃?5條。

          所以出現(xiàn)了這個代碼:

          Map<String, String> map = new HashMap<>(15);

          或者是

          Map<String, String> map = new HashMap<>(userPageList.size());
          錯誤理解使用示例 ② :

          類型type 有 4種, 要放到一個map里面,返回去。

          所以出現(xiàn)了這個代碼:

          Map<Integer, String> map = new HashMap<>(4);
          錯誤理解使用示例 ③:

          一個參數(shù)map,里面想放2個參數(shù)。

          所以出現(xiàn)了這個代碼:

          Map<String, String> map = new HashMap<>(2);

          不多舉例,其實(shí)這幾個錯誤示例,都是錯在指定容量的 值上。

          默認(rèn) 指定是 傳入 16, 16* 0.75=12 , 所以擴(kuò)容閾值是12 。

          說到這里,大家應(yīng)該知道為什么上面是錯誤用法了吧?

          比如我們想 存 4個元素到Map, 我們?yōu)榱吮苊夂竺嬗|發(fā)擴(kuò)容影響性能(其實(shí)元素少性能沒多少影響), 就指定了 4 :

          Map<Integer, String> map = new HashMap<>(4);

          其實(shí)這樣 4x0.75= 3 ,那么如果存放第四個元素的時候,就會觸發(fā)擴(kuò)容

          這樣就是違背了我們開始指定 的 4 的最初用意。

          實(shí)戰(zhàn)看看這個錯誤使用場景的情況:

          同過反射,將capacity屬性的權(quán)限拿到,可以直接打印出來看下capacity的變化,就知道是否觸發(fā)了擴(kuò)容:

          public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

              Map<String, String> map = new HashMap<>(4);
              Class<?> mapType = map.getClass();
              Method capacity = mapType.getDeclaredMethod("capacity");
              capacity.setAccessible(true);

              map.put("1""第一個元素插入");
              System.out.println("capacity : " + capacity.invoke(map) + "    size : " + map.size());
              map.put("2""第二個元素插入");
              System.out.println("capacity : " + capacity.invoke(map) + "    size : " + map.size());
              map.put("3""第三個元素插入");
              System.out.println("capacity : " + capacity.invoke(map) + "    size : " + map.size());
              map.put("4""第四個元素插入");
              System.out.println("capacity : " + capacity.invoke(map) + "    size : " + map.size());

          }

          看下打印效果:

          為什么,當(dāng)size =3 ,也就是插入三個元素的時候還沒變。

          因?yàn)槲覀兂跏蓟萘恐祩魅氲?4,  4* 0.75 =3. 擴(kuò)容閾值是 3!

          當(dāng)插入第四個元素的時候, 就超過了擴(kuò)容閾值,所以觸發(fā)了擴(kuò)容,所以看的最后其實(shí)是進(jìn)行了一次擴(kuò)容,打印出來的capacity是 8.

          那么我們應(yīng)該傳多少?

          4/0.75  + 1 = 6.3333333

          我們指定傳6么?還是傳 7 ?

          指定6:

          指定7:

          指定6,7 都沒區(qū)別好像, 值得慶祝的是,沒有再次觸發(fā)擴(kuò)容。

          那么為啥沒區(qū)別呢?

          HashMap會轉(zhuǎn)換成大于該capacity 的第一個2的冪作為容量 。

          所以傳5,6,7,8 都是 8 ;

          傳9,10,11,12,13,14,15,16 都是 16 ;

          好了不多啰嗦了, 最后再補(bǔ)一嘴, 默認(rèn)指定容量,其實(shí)就是 內(nèi)存換性能。

          所以真正去使用指定容量的時候, 需要考慮:如果我是一個定時任務(wù),允許跑1小時。。。我需要考慮性能么?

          或者如果我服務(wù)內(nèi)存很小,我是不是要對內(nèi)存省吃儉用?


          到此文章就結(jié)束了。Java架構(gòu)師必看一個集公眾號、小程序、網(wǎng)站(3合1的文章平臺,給您架構(gòu)路上一臂之力,javajgs.com)。如果今天的文章對你在進(jìn)階架構(gòu)師的路上有新的啟發(fā)和進(jìn)步,歡迎轉(zhuǎn)發(fā)給更多人。歡迎加入架構(gòu)師社區(qū)技術(shù)交流群,眾多大咖帶你進(jìn)階架構(gòu)師,在后臺回復(fù)“加群”即可入群。

          第23期已結(jié)束!第24期已開始,11月1號截止



          這些年小編給你分享過的干貨


          1.idea永久激活碼(親測可用)

          2.優(yōu)質(zhì)ERP系統(tǒng)帶進(jìn)銷存財(cái)務(wù)生產(chǎn)功能(附源碼)

          3.優(yōu)質(zhì)SpringBoot帶工作流管理項(xiàng)目(附源碼)

          4.最好用的OA系統(tǒng),拿來即用(附源碼)

          5.SBoot+Vue外賣系統(tǒng)前后端都有(附源碼

          6.SBoot+Vue可視化大屏拖拽項(xiàng)目(附源碼)


          轉(zhuǎn)發(fā)在看就是最大的支持??

          瀏覽 35
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  黄色视频免费在线观看 | 在线免费观看a视频 | 欧美日韩亚洲中文字幕 | 国产逼网 | 亚欧洲精品在线视频免费观看 |