最通俗易懂搞定HashMap的底層原理

yilian發表於2019-12-06

HashMap的底層原理面試必考題

為什麼面試官如此青睞這道題?

HashMap裡面涉及了很多的知識點,可以比較全面考察面試者的基本功,想要拿到一個好offer,這是一個邁不過的坎,接下來我用最通俗易懂的語言帶著大家揭開HashMap的神秘面紗

一:HashMap的節點:HashMap是一個集合,鍵值對的集合,原始碼中每個節點用Node<K,V>表示

static class Node<K,V> implements Map.Entry<K,V> {   final int hash;   final K key;
   V value;
   Node<K,V> next;

Node是一個內部類,這裡的key為鍵,value為值,next指向下一個元素,可以看出HashMap中的元素不是一個單純的鍵值對, 還包含下一個元素的引用

二:HashMap的資料結構:HashMap的資料結構為  陣列+(連結串列或紅黑樹),上圖:

image.png
image.png

為什麼採用這種結構來儲存元素呢?

陣列的特點:查詢效率高,插入,刪除效率低

連結串列的特點:查詢效率低,插入刪除效率高

在HashMap底層使用陣列加(連結串列或紅黑樹)的結構完美的解決了陣列和連結串列的問題,使得查詢和插入,刪除的效率都很高。

三:HashMap儲存元素的過程:

有這樣一段程式碼:

HashMap<String,String> map = new HashMap<String,String>();
map.put("劉德華","張惠妹");
map.put("張學友","大S");

現在我要把鍵值對 “劉德華”,”張惠妹”存入map:

第一步:計算出鍵“劉德華”的hashcode,該值用來定位要將這個元素存放到陣列中的什麼位置.

什麼是hashcode?

在Object類中有一個方法:

public native int hashCode();

該方法用native修飾,所以是一個本地方法,所謂本地方法就是非java程式碼,這個程式碼通常用c或c++寫成,在java中可以去呼叫它。

呼叫這個方法會生成一個int型的整數,我們叫它雜湊碼,雜湊碼和呼叫它的物件地址和內容有關.

雜湊碼的特點是:

對於同一個物件如果沒有被修改(使用equals比較返回true)那麼無論何時它的hashcode值都是相同的

對於兩個物件如果他們的equals返回false,那麼他們的hashcode值也有可能相等

明白了hashcode我們再來看元素如何透過hashcode定位到要儲存在陣列的哪裡,透過hashcode值和陣列長度取模我們可以得到元素儲存的下標。

劉德華的hashcode為20977295 陣列長度為 16則要儲存在陣列索引為 20977295%16=1的地方

1.jpg
1.jpg

可以分兩種情況:

1. 陣列索引為1的地方是空的,這種情況很簡單,直接將元素放進去就好了。

2. 已經有元素佔據了索引為1的位置,這種情況下我們需要判斷一下該位置的元素和當前元素是否相等,使用equals來比較。

如果使用預設的規則是比較兩個物件的地址。也就是兩者需要是同一個物件才相等,當然我們也可以重寫equals方法來實現我們自己的比較規則最常見的是透過比較屬性值來判斷是否相等。

如果兩者相等則直接覆蓋如果不等則在原元素下面使用連結串列的結構儲存該元素

2.jpg
2.jpg

每個元素節點都有一個next屬性指向下一個節點,這裡由陣列結構變成了陣列+連結串列結構,紅黑樹又是怎麼回事呢?

因為連結串列中元素太多的時候會影響查詢效率,所以當連結串列的元素個數達到8的時候使用連結串列儲存就轉變成了使用紅黑樹儲存,原因就是 紅黑樹是平衡二叉樹,在查詢效能方面比連結串列要高.

四:HashMap中的兩個重要的引數:HashMap中有兩個重要的引數: 初始容量大小和載入因子,初始容量大小是建立時給陣列分配的容量大小,預設值為16, 用陣列容量大小乘以載入因子得到一個值,一旦陣列中儲存的元素個數超過該值就會呼叫rehash方法將陣列容量增加到原來的兩倍,專業術語叫做擴容.

在做擴容的時候會生成一個新的陣列,原來的所有資料需要重新計算雜湊碼值重新分配到新的陣列,所以擴容的操作非常消耗效能.

image.png
image.png

建立HashMap時我們可以透過合理的設定初始容量大小來達到儘量少的擴容的目的。載入因子也可以設定,但是除非特殊情況不建議設定.




來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69952849/viewspace-2667314/,如需轉載,請註明出處,否則將追究法律責任。

相關文章