斷定Java程序員等級,HashMap就夠了

                                         JDK1.8  HashMap源碼分析算法

用到的符號:數組

     ^異運算:兩個操做數相同,結果是;兩個操做數不一樣,結果是1。函數

     &按位與:兩個操做數都是1,結果纔是1。源碼分析

1、HashMap概述性能

     在JDK1.8以前,HashMap採用數組+鏈表實現,即便用鏈表處理衝突,同一hash值的鏈表都存儲在一個鏈表裏。可是當位於一個桶中的元素較多,即hash值相等的元素較多時,經過key值依次查找的效率較低。而JDK1.8中,HashMap採用數組+鏈表+紅黑樹(二叉樹的優化實現是一種平衡二叉樹,能夠下降數的深度)實現,當鏈表長度超過閾值(8)時,將鏈表轉換爲紅黑樹,這樣大大減小了查找時間。優化

      

 

    jdk1.8以前的hashmap都採用上圖的結構,都是基於一個數組和多個單鏈表,hash值衝突的時候,就將對應節點以鏈表的形式存儲。若是在一個鏈表中查找其中一個節點時,將會花費O(n)的查找時間,會有很大的性能損失。到了jdk1.8,當同一個hash值的節點數不小於8時,再也不採用單鏈表形式存儲,而是採用紅黑樹。blog

                      

2、瞭解Hash函數源碼

   咱們先了解一下Hash的源碼:hash

    

    代碼執行過程:若是key爲空,返回0;若是key不爲空,返回原hash值和原hash值無符號右移16位的值按位異或的結果。(把低16位和高16位進行異或運算)。由於低位重複機率計算大,低位和高位異或運算能夠提交數組的利用率,使數組分佈均勻。table

    按位異或就是把兩個數按二進制,相同就取0,不一樣就取1。

    好比:0101 ^ 1110 的結果爲 1011,異或的速度是很是快的。

   把一個數右移16位即丟棄低16爲,就是任何小於216的數,右移16後結果都爲0(2的16次方再右移恰好就是1)。

   任何一個數,與0按位異或的結果都是這個數自己。

   因此這個hash()函數對於非null的hash值,僅在其大於等於216的時候纔會從新調整其值。

   可是調整後又什麼好處呢?

   咱們先看下put的時候,這個hash值是怎麼處理(部分源碼)的:

   

    在尋找桶位的時候,這個hash值爲與上table的zise-1,初始爲16,咱們就拿16來舉例.

    覺得算法是hashValue & size - 1 ,此時size-1=15的二進制爲 1 1 1 1 ,也就是任意相似16進制0x?0(二進制最後四位爲0000)的hash值,都會被存儲到位置爲0的桶位上,一個桶中的元素太多,就必定會下降其性能。咱們知道HashMap是一個數組+鏈表,就是在下標相同的位置下面掛一個單項的鏈表,那數組的下標須要計算出來,必須保證在必定的範圍內,是經過【(n-1)&hash】計算機計算的是二進制,好比數組大小必須是2的N次冪,權重是0.75,數組初始值是16,權重等於12(16*0.75),當等於12數組會擴容。擴容以後對數組進行從新分配。當鏈表的大小大於8的時候會轉化爲紅黑樹。數組下標計算方式:(0101010101010101010101010101&00000000000000000001111)以16來講,十六進制的二進制表示後面的0,N-1的二進制結尾是1111,二者進行與操做最大值是1111,1111的16十六進制是15,而後把Node節點放入這個位置,這樣來計算下標。

總結以下:

 

相關文章
相關標籤/搜索