廢話不多說,直接閱讀源碼。如果你實在無閒暇看無聊的代碼閱讀,可以閱讀每段的標題或者最後的總結。
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算法後的數值決定。這也就是爲什麼存進去的順序和取出來的順序不相同的原因。
總結
- HashMap的內部由一個對象數組存儲,但是順序不由數組決定。
- HashMap類似於單鏈表結構。
- HashMap是無序的單鏈表結構,並且順序由內置的hash算法決定。
參考文章
文章中出現的任何錯誤歡迎指正!共同進步!
最後做個小小廣告,有對WEB開發和網絡安全感興趣的,可以加羣一起學習和交流!
QQ:425343603