HashMap源代碼閱讀小結

這裏將我的閱讀源代碼後得到的信息以文字不帶代碼的方式寫出來,我的認爲有助於本身在面試時候更清晰表達本身想說的東西。面試

HashMap底層實現原理:以數組爲主幹,鏈表爲分支的方式存儲數據。數組中的全部key-value的key的hash值都不相同;鏈表中,全部key-value的key的hash值相同。算法

具體添加數據(put方法)時,若是根據key計算出的hash值對應的位置沒有數據,則將須要添加的數據放在hash值對應的位置上,若是對應的位置已存在數據,則將新數據的next引用指向數組中的key-value數據,而後將新數據放到數組中hash值對應的位置上。固然hash值的算法已經作了足夠的優化來儘可能避免不一樣的key進行hash計算產生相同的hash值,而且儘可能使數組中的位置可以獲得充分的使用,以提升數據獲取時的查詢效率。數組

得到數據時(get方法)首先根據key的hash值,找到數組中對應的位置,而後經過比較key是否相同,找到對應的value。安全

對於HashMap使用的一些注意點:構造方法有3個:無任何參數;帶一個初始容量;帶初始容量和負載因子;函數

初始容量簡單的說是HashMap中數組最開始沒有擴容前的長度,還有一個size是指存儲在hashMap中的key-value對數,極限容量爲當前容量與負載因子乘積的整數部分。當size值超過極限容量時,HashMap須要擴容。性能

初始容量的計算:調用構造方法時,若是未指定初始容量,則使用默認初始容量爲16,源碼中以 1<<4 表示,若是指定了初始容量參數,若是參數值爲2的n次方值,則該值即爲HashMap初始容量,不然爲大於該值的最小2的n次方值,如參數值爲6,則初始容量爲8,參數值爲14時,初始容量爲16。注意:該值並不是在調用構造方法進行實例化的時候肯定的,是在初次調用put方法時肯定的。也就是說HashMap數組的長度最開始是在初次調用put方法時才肯定的,存儲空間也是初次調用put方法時申請的。優化

在這個過程當中,hashMap的極限容量可能發生變化,按照通常的理解,在調用構造方法時指定初始容量,代表後續的操做過程當中,將在該hashMap中存入初始容量個key-value,在構造函數中確實是如此處理的,初始容量的參數值被賦值給極限容量,可是在put方法中進行初始容量再計算時,極限容量從新計算爲初始容量與負載因子的乘積,也就是說假如調用構造函數時傳入的初始容量爲7,負載因子爲0.75,在未調用put方法前,hashMap的極限容量都是7,可是當存入第一個key-value後,hashmap的初始容量肯定爲8,此時極限容量從新計算爲6,那麼按照道理來講,在指定了初始容量以後,並無徹底的杜絕擴容問題,不知道你們有沒有發現過這個問題,仍是我有哪些地方理解誤差了。線程

擴容:當size 大於等於極限容量時,hashmap會擴容爲當前容量(數組長度)的兩倍。擴容後,需從新計算各個key-value在數組中的位置。因此hashmap擴容操做是至關消耗性能的。get

hashMap不是線程安全的,若是在使用迭代器的過程當中有其餘線程修改了map,將拋出ConcurrentModificationException,這就是所謂fail-fast策略,而其餘線程經過其餘方式進行操做是沒法識別的。源碼

 

以上爲小結所有內容,看到有誤或不足之處請你們不吝指正,在此很是感謝!

相關文章
相關標籤/搜索