大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 hot資訊 HashMap的擴容機制

HashMap的擴容機制

更新時間:2022-05-17 10:14:56 來源:動力節點 瀏覽2461次

先說擴容原理

在jdk1.7中,擴容需要滿足以下兩個條件:

1.存儲新值時已有元素的個數必須大于等于閾值

2.當前存儲數據發生在新值存儲hash時碰撞

在jdk1.8中,擴容只需要滿足一個條件:當前存儲新值時已有元素的個數大于等于閾值(注意不替換已有元素)(已有元素等于閾值,下一個存儲必然會觸發擴容機制)或者將數據保存到鏈表中。這時候如果數據大于8,總數小于64,就會發生擴容。注意:

(1)擴展必須在放置新值的時候,新值不在替換之前位置的情況下

(2)擴展發生后,會判斷存儲的對象個數。如果大于閾值,將執行擴展。

(3)第一次put的時候,先觸發擴容(實例化的HashMap的內部數組默認為null,即不實例化。第一次調用put方法時,會先啟動初始化和擴展,長度為16.),然后保存數據,然后判斷是否需要擴展;如果不是第一次,則不會再次初始化。直接保存數據,然后判斷是否需要擴容;

HashMap的容量有一個上限,必須小于1<<30,即1073741824。如果容量超過這個數,就不再增加,閾值設置為Integer.MAX_VALUE([公式] ,即永遠不會超過閾值)。

源碼:jdk7中new Hashmap()時初始化對象,而jdk8中new Hashmap()并沒有初始化對象,而是在put()方法中通過判斷對象是否為空,如果為Null初始化通過調用 resize() 對象。

	 public V put ( K key , V value )  { 
       	 return  putVal ( hash ( key ) , key , value ,  false ,  true ) ; 
    	} 
/**
     * 實現 Map.put 及相關方法
     *
     * @param 哈希鍵值計算傳遞下標
     * @參數鍵
     * @參數值
     * @param onlyIfAbsent true 只在值為空時存儲數據,false 存儲數據
     * @param 驅逐
     * @return 返回覆蓋的值,如果沒有覆蓋則返回 null
     */ 
    final V putVal ( int hash , K key , V value ,  boolean onlyIfAbsent ,                    boolean evict )  { 
        //聲明入口數組 object tab[]: current Entry[] object  
        Node < K , V > [ ] tab ; 
        //聲明入口對象p:這里表示存儲的單個節點 
        Node < K , V > p ;
        //n:為當前Entry對象的長度//i:為下標
        int n , i為當前存放對象節點的位置;
        /**
         * 過程判斷
         * 1.如果當前Node數組(tab)為空,直接創建(通過resize()創建),創建后設置當前長度為n
         * 2.如果要存儲對象的Node節點為空,直接在對象存儲位置新建Node,直接存儲值
         * 3.存儲的Node數組不為空,存儲的下標節點Node不為空(Node節點為鏈表的第一個節點)
         * 1) 比較存儲在鏈表第一個節點的對象和當前對象是否為同一個對象,如果是則覆蓋并返回原值
         * 2) 如果不分兩種情況
         * (1)存儲節點為紅黑樹節點結構,調用putTreeVal()方法直接插入數據
         * (2)如果不是紅黑樹,則表示為鏈表,遍歷
         * A.如果存儲的鏈表的下一個位置為空,先直接存儲該值,保存后再檢查當前存儲的位置是否大于鏈表的第8位
         * 一種。如果大于,則調用treeifyBin方法判斷是否對鏈表進行擴展或轉換為紅黑樹(大于8且總數據量大于64,則轉紅黑,否則為數組將擴大)
         * b。當前保存的位置鏈表長度不大于8,則保存成功,終端循環操作。
         * B. 如果鏈表中存儲的下一個位置有值,且該值與存儲的對象“相同”,則直接覆蓋,返回原值
         * 以上兩種情況AB執行后,判斷返回的原始對象是否為空,如果不是,則返回原始對象的原始值
         * 上述123三種情況中,如果原值沒有被覆蓋,則表示新增了新存儲的數據。數據存儲后,size+1,然后判斷當前數據量是否大于閾值。
         * 如果大于閾值,則擴容。
         * 
        / if  ( ( tab = table )  == null ||  ( n = tab.length ) == 0 )  
            n = ( tab = resize ( ) ) 。 _ 長度;if ( ( p = tab [ i = ( n - 1 ) & hash ] ) == null    
             ) 
            tab [ i ]  =  newNode ( hash , key , value , null ) ; 
        否則 { 
            節點< K , V > e ; ?? ; 
            if  ( p . hash == hash && 
                    ( ( k = p . key )  == key ||  ( key != null&&鍵等于( . k ) ) ) )  
                e = p ; 
            else  if  ( p instanceof  TreeNode ) 
                //直接將數據存入紅黑樹 
                e =  ( ( TreeNode < K , V > ) p ) . putTreeVal (這,選項卡,哈希,鍵,值); 
            else  { 
                for  ( int binCount =  0 ;  ;  ++ ; binCount )  { 
                    if  ( ( e = p . next )  == null )  {  
                        p . next =  newNode (哈希,鍵,值, null ) ; 
                        如果 ( binCount >= TREEIFY_THRESHOLD - 1 )  //-1 for 1st 
                            treeifyBin ( tab , hash ) //該方法判斷是擴展還是需要將鏈表轉換為紅黑樹break ;}                                          
                    if  ( e . Hash == hash && 
                            ( ( k = e . Key )  == key ||  ( key ! = null && key . Equals ( k ) ) ) )
                        ;  
                    p = e ; 
                } 
            } 
            if  ( e != null )  {  //key  
                V oldValue = e的現有映射。價值;if ( ! onlyIfAbsent || oldValue == null )  
                    e . 價值=價值;afterNodeAccess ( e ) ; 返回舊值;} }     
        ++ modCount ; 
        //如果不是替換數據保存,而是新位置保存后,地圖大小加1,然后判斷容量是否超過閾值,如果超過則擴容
        if  ( ++ size > threshold )
            調整大小( ) ; 
        afterNodeInsertion (驅逐) ; 
        返回空值;
    }

treeifyBin() 方法判斷是否將當前鏈表展開或轉換為紅黑樹

/**
     * 替換給定哈希索引處 bin 中的所有鏈接節點,除非
     * 表太小,在這種情況下調整大小。
     * 從鏈表中指定哈希位置的節點開始,全部替換為紅黑樹結構。
     * 除非整個數組對象(Map集合)的數據量非常小(小于64),這種情況下Map是通過resize()來擴展的,而不是把鏈表轉化為紅黑樹。
     */ 
    final  void  treeifyBin ( HashMap . Node < K , V > [ ] tab ,  int hash )  { 
        int n , index ; 哈希映射。節點< K , V > e ; 
        //如果Map為空或者當前存儲數據n(可以理解為map的size())個數小于64,然后進行擴容
        if  ( tab == null||  ( n = tab.Length ) < MIN_TREEIFY_CAPACITY )調整大小( ) ; _  //如果size()大于64,則將存儲值的鏈表轉換為紅黑樹else if ( ( e = tab [ index = ( n - 1 ) & hash ] ) != null ) { 
            哈希映射。樹節點< K ,                    
               V > hd = null , tl = null ; 
            做 { 
                哈希映射。TreeNode < K , V > p =  replacementTreeNode ( e , null ) ; 
                如果 ( tl == null )  
                    hd = p ; 
                否則 {  
                    p 。上一頁= tl ;  
                    tl. 下一個= p ; 
                }  
                tl = p ; 
            }  while  ( ( e = e . next )  != null ) ; 
            如果 ((標簽[索引]  =高清) !=空) 
                高清。樹化(選項卡);
        } 
    }

子問題一:哈希算法

Java 源代碼執行此操作:

先根據key計算hashCode值,然后對數組長度減一做AND運算。為什么當 hashmap 數組的初始大小是 2 的冪時,hashmap 效率最高?你可以看到第七個問題。因此,當數組長度為2的n次冪時,不同key計算的索引相同的概率較小,則數據在數組上分布更均勻,查詢效率更高.

HashMap中默認的數組大小為16,因為16是2的整數次冪,在數據量較小的情況下可以更好的減少key之間的沖突。存儲大容量時,最好預先指定HashMap的大小為2的整數次冪。如果不指定,HashMap的構造方法也會初始化為大于和最接近指定的2次冪價值。

子問題2:HashMap的resize

HashMap展開時:必須重新計算原數組中的數組,放入新數組中。這是調整大小。那么我們什么時候應該擴張呢?當 HashMap 中的元素個數超過數組大小 * loadFactor(加載因子)時,數組會被擴展。loadFactor 的默認值為 0.75。

所以一開始,在指定HashMap的大小時,我們把它設置為最接近我們預期的數/0.75,得到最接近并大于他的數(這個數是2的指數倍數),所以我們同時考慮 & 的問題,也避免了調整大小的問題。

如果大家對此比較感興趣,想了解更多相關知識,可以關注一下動力節點的HashMap擴容機制解讀,里面有更豐富的知識等著大家去學習,希望對大家能夠有所幫助哦。

提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 天天干天天草 | 老司机午夜免费影院 | 2020久久精品永久免费 | 97久久精品国产精品青草 | 亚洲精品在线不卡 | 色综合天天综合网国产国产人 | 欧美在线一区二区 | 在线观看a视频 | 欧美一a一片一级一片 | 国产亚洲高清在线精品99 | 久久99精品久久久久久水蜜桃 | 日韩欧一级毛片在线播无遮挡 | 国产精品欧美亚洲韩国日本 | 被黑人做的白浆直流在线播放 | 天天做天天爱天天一爽一毛片 | 亚洲国产天堂久久九九九 | 国产美女久久久久久久久久久 | 九九久久视频 | 欧洲成人免费高清视频 | 九九精品国产兔费观看久久 | 免费特黄一级欧美大片 | 成人国产精品视频频 | 在线免费精品视频 | 老头老太做爰xxx视频 | 久久久在线视频精品免费观看 | 久久久国产在线 | 香蕉超级碰碰碰97视频蜜芽 | 夜夜摸视频网 | 老司机免费福利视频无毒午夜 | 国产福利视精品永久免费 | 日韩日b视频 | 国产91成人 | 香蕉视频在线观看网站 | 久久99热精品免费观看k影院 | 久久99爱爱 | 黄色在线免费看 | 欧美成人免费毛片 | 国产精品第 | 久久久久久国产精品免费 | 狠狠色狠色综合曰曰 | 欧美亚洲国产色综合 |