如下講解基於JDK1.7html
HashMap底層是一個數組,哈希值相同的元素放在數組中的相同的位置,多個相同哈希值的元素造成一個鏈表。也就是說,元素的組織形式是單向鏈表。數組
下面從put、get、remove這三個方法分析一下源代碼,看看HashMap增刪查改是怎麼作的。數據結構
構造HashMap對象的時候作了初始化,指定默認的初始容量(數組長度)和增加因子併發
接下來,從put開始分析ide
從上面三段代碼能夠看出添加一個元素的基本流程:ui
(1)HashMap的key值容許爲null,並且key爲null的元素放在數組中下標爲0的位置spa
(2)根據待插入元素的key值計算出一個哈希值,而後根據這個哈希值和數組的長度計算該元素將要放置的位置(PS:下標)。若是這個位置爲空,那麼直接插入。不然,遍歷該位置上的鏈表,依次比較他們的key值是否相同,若是相同,則將用新值替換舊值,而後返回就值。.net
(3)正常插入,將待插入的元素放置在鏈表的頭部,而後將其指向原先的鏈表頭部(即:原先放置在待插入位置的元素)。也就是說,新插入的元素是放在頭部的,我以爲這樣作的好處多是根據LRU的原則減小遍歷的次數。線程
(4)有一種特殊狀況是,擴容。3d
擴容就是,將原數組中的每一個位置的元素都遷移到新數組中,在遷移到新數組的過程當中一樣先計算哈希值,而後得出將要放置在新數組中那個位置上。鏈表的遷移過程至關於將原先的鏈表倒置,先將頭部的元素遷移過去,而後將下一個元素遷移過去,令next元素的next指向新數組位置上的元素,最終呈現出來的效果就是鏈表倒置。
接下來看get操做
get操做比較簡單:
(1)根據key算哈希值,進而得出元素可能的位置,而後遍歷該位置上的鏈表,比較key值是否相同,相同則返回,不然返回null
最後是remove
刪除也相對比較簡單:
(1)刪除元素所在位置,遍歷鏈表,比較key值,找到待刪除元素之後,若是當前只有一個元素,直接刪除,此位置置位NULL,不然將前面元素的next指向後面元素。
HashMap在併發狀況下存在的問題(併發就是無法保證順序)
(1)插入的元素可能被覆蓋
假設有兩個線程都執行到這裏,線程1它的key=A,value=aaa,線程2它的key=B,value=bbb。
假設i=1,那麼線程1執行的時候table[1]=new Entry<>(1234, "A", "aaa", null);
等到線程2執行的時候table[1]=new Entry<>(1234, "B", "bbb", null);
因而乎,線程1插入的數據就丟失了(或者說是被覆蓋了)
(2)put的時候,鏈表可能造成環形數據結構,致使若是查找一個不存在的元素時死循環
那麼環狀是怎麼造成的呢?發生在擴容的時候。請看圖
假設有兩個元素A和B,它們的關係是A.next=B,B.next=null
大概就是下面這個樣子
假設有兩個線程,線程-1和線程-2,它們在執行插入的時候都發現須要擴容,因而乎都開始擴容。
固然,擴容是在它們本身的內存中進行的。假設線程-1完成對A元素的遷移後準備對B進行遷移並執行到Entry<K,V> next = e.next;時還沒執行時線程被掛起了。執行到線程-2先執行完擴容,因而擴容後的指向關係變成了這個樣子:B.next=A,A.next=null
特別注意,看圖上畫的好像是元素直接放到數組的某個位置,但咱們要知道,其它放的是元素的地址,也就是說元素自己的位置不變,修改的只是指針指向。儘管線程-2構造的新數組對線程-1而言是不可見的,可是不能否認,線程-2在擴容過程當中已經將A和B的指向關係修改了,也就是說,此時,B是指向A的,這一點對線程-1而言是可見的。
接下來,線程-1醒來,繼續執行
while(null != e) {
Entry<,> next = e.; (rehash) { e.= == e.? : hash(e.); } i = (e., newCapacity); e.= newTable[i]; newTable[i] = e; e = next; }
此時,對照代碼應該是這樣的
通過這一遍,如今在新數組中的指向關係變成:B-->A-->NULL
緊接着,由於e已是A了,因此null != e,因而再執行一遍
而後就變成這樣了
接下來,麻煩來了。
查找C,通過計算C應該與A、B在數組的同一個位置,因而遍歷鏈表
因而,經過A找到B,經過B又找到A,經過A又找到B,經過B又找到A,如此反覆,永遠都不爲null,死循環
終於講明白了
最後,再提一點,就是hash方法,字符串和非字符串算哈希值的方法是不同的
參考:
http://blog.csdn.net/zhuqiuhui/article/details/51849692
https://www.cnblogs.com/binyue/p/3726403.html