【HashMap】HashMap底層資料結構
HashMap:散列表集合,實現了Map介面,Map又實現了Iterator介面。遍歷Map可以用Iteratoer實現,也可以用Entry(HashMap內部類)實現
兩種實現方式:
while(iterator.hasNext)
for(map.Entry entry : map.getEntrySet())
資料結構:陣列+連結串列
陣列:儲存區間是連續的,佔用記憶體大,存慢,取值快;
連結串列的儲存區間離散,佔用記憶體寬鬆,增值快,取值慢;
兩者結合起來,就實現了HashMap:存、取都很快。
那麼,兩者具體是怎麼結合的呢?
HashMap裡有一個數組Node<K,V>[]預設16個,儲存的K、V、hash、next(Node)。(Node<K,V>實現了Entry<K,V>介面,它其實就是一個Entry)
put(K,V)——>根據K算出下標i,鍵值對存在i處,newNode(hash,key,value,next)形成一條資料鏈,
get(K)——>getNode(hash,key),根據key算出下標i,取出i位置的Node<K,V>,比較hash,如果相同就直接返回,如果不同繼續next,直到沒有next了為止。
<陣列預設16個>
(0) Entry<K,V> ---put的資料---put的資料 ——>代表陣列下標i=0處,存的資料(鍵值對)
(1) Entry<K,V> ---put的資料---put的資料 ——>代表陣列下標i=1處,存的資料(鍵值對)
...
(15)..........................................................——>代表陣列下標i=15處,存的資料(鍵值對)
Node<K,V>位置i:key的雜湊值,對(陣列長度-1)取模,(len-1) & hash相當於取模,這裡暫且將取模認為是取餘,下面好理解
i:0、1、2...15
key的雜湊值:3、18;1、16;
確定i位置:3、18對15取餘,鍵值對就存在i=3後面;1、16對15取餘,鍵值對就存在i=1後面
取模:5 mod -3 = -1,結果的+-取決於-3;讓結果儘可能小(因為商的值向負無窮捨棄小數位)<=取餘結果
取餘:5 % -3 = 2,結果的+-取決於5;讓結果儘可能大(因為商的值向0方向捨棄小數位)
拿取餘作為例子:5/3 =1.6666(不捨棄小數位的話),3-1.66666<2;由於商的值向0方向捨棄小數位,所以3-1=2
據上所述,每個陣列元素後邊都跟了一個鏈條,這就存在取值效率問題了,紅黑樹很好的解決了這個問題(TreeNode<K,V> 也實現了Entry介面,和Node不同的是,多了left、right等屬性,用於交換位置,提高取值效率,如下)。
8 8
7 7
6 6
5 4 5
4