【Java面試】徹底搞懂HashMap

廢話不多說,直接閱讀源碼。如果你實在無閒暇看無聊的代碼閱讀,可以閱讀每段的標題或者最後的總結。


HashMap結構

transient <K,V>[] table;

實際上HashMap內就是由多個Node<K, V>對象組成的數組,如果你暫時還不知道泛型的話,那可能還是看不明白,我用Object[]這樣來解釋是不是更清楚呢,雖然兩者是完全不相同,但是爲了理解這個東西。

而這個對象內又包含着哪些屬性組成呢?

final int hash;
final K key;
V value;
Node<K,V> next;

hash則是右key通過獲得對象的hashCode得到的值和hashCode之後的值無符號右移16位之後異或得到,在代碼中他的算法是這樣的,這裏就不深究了具體怎麼計算了。

key.hashCode()) ^ (h >>> 16)

後面的幾個屬性我們通過put方法debug看看他們是怎麼被設置的吧!

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

put的核心方法在putVal中,一打開一大把的邏輯把我看暈了,我過濾掉一些無關的代碼細節,直接揪出新建Node對象和設置的地方。

tab[i] = newNode(hash, key, value, null);

是不是覺得就這?但是重點了來了,next這個最重要的屬性到哪裏去了,但是邏輯真的好麻煩不想看,硬着頭皮繼續debug。

首先put兩個對象,因爲只有一個對象的時候,這裏的next會爲null。

HashMap hashMap = new HashMap();
hashMap.put("1", "1");
hashMap.put("2", "2");

直接就進到了這個方法,又是一連串的邏輯!

resize();

這裏就是計算和設置next屬性的地方,有興趣的可以仔細閱讀源碼。


單鏈表

到這裏如果有數據結構基礎的人應該差不多明白了百分之80了,就是鏈表的存儲結構。

如果還是不清楚的話,那麼我給大家畫幾張圖就明白了。
單鏈表圖

無序的單鏈表

但是有個問題既然是數組,那麼應該是有序的纔對,那麼爲什麼HashMap常常被人說是無序的呢?可能是我們漏看了哪裏,我們從遍歷的順序來看看到底什麼原因。

 HashMap hashMap = new HashMap();

for (int i = 0; i < 1000; i++) {
    hashMap.put(String.valueOf(i), String.valueOf(i));
}

Iterator it = hashMap.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry entry = (Map.Entry) it.next();
    String key = (String) entry.getKey();
    String value = (String) entry.getValue();
    System.out.println("key:" + key + "---" + "value:" + value);
        }

截取一小部分的結果

key:623---value:623
key:865---value:865
key:624---value:624
key:866---value:866
key:625---value:625
key:867---value:867
key:626---value:626
key:868---value:868
key:627---value:627

一路跟進到最後找到

HashIterator() {
  expectedModCount = modCount;
    Node<K,V>[] t = table;
    current = next = null;
    index = 0;
    if (t != null && size > 0) { // advance to first entry
        do {} while (index < t.length && (next = t[index++]) == null);
    }
}

雖然還是在遍歷最初的對象數組,看起來實際上是通過有順序的數組遍歷的,但是當他把next設置爲其他對象的時候,最後的順序就不是按照數組的順序去取數了,而這個順序由hash算法後的數值決定。這也就是爲什麼存進去的順序和取出來的順序不相同的原因。


總結

  1. HashMap的內部由一個對象數組存儲,但是順序不由數組決定。
  2. HashMap類似於單鏈表結構。
  3. HashMap是無序的單鏈表結構,並且順序由內置的hash算法決定。

參考文章

淺談HashMap原理,記錄entrySet中的一些疑問

文章中出現的任何錯誤歡迎指正!共同進步!

最後做個小小廣告,有對WEB開發和網絡安全感興趣的,可以加羣一起學習和交流!

交流羣
QQ:425343603

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章