概念
1、hashmap 是對map接口的實現(xiàn)
2、hashmap底層是將key-value當成一個整體進行處理,這個整體就是一個Entry對象。hashmap底層采用Entry[]數(shù)組來保存所有的key-value.
3、存儲一個entry對象時,會利用hash算法根據(jù)key計算出hashcode值來決定其在數(shù)組中的位置。當出現(xiàn)hashcode值相同時,則會發(fā)生hash碰撞,接著會將值以鏈表的形式存儲在一起。
4、當獲取值時,根據(jù)key找到對應entry數(shù)組的位置,然后遍歷鏈表,通過keys.equals()方法找到對象。
面試點
1、hashmap的初始容量 16 2的冪次方
2、hashmap的負載因子(load) 默認0.75
3、何時會發(fā)生容量擴容:
1)當size/capacity大于默認負載因子時。
2)size是所有key-value的總數(shù)
3)capacity是容量,capacity就是指HashMap中桶的數(shù)量
4、擴容的大小:第一次會由16變成64,之后每次是原來的兩倍
5、當兩個對象的hashcode相同時會發(fā)生什么
·會發(fā)生hash碰撞,該對象會被存儲在同一個bucket下,以鏈表的形式結合,jdk1.8中當鏈表長度超過8時,會生成紅黑樹的形式
6、如何減少碰撞的發(fā)生
·使用string和integer這種包裝類作為key
·因為他們是final類型的,不可變性
7、重新調(diào)整hashmap的大小存在什么問題
·1、多線程情況下,出現(xiàn)條件競爭:會出現(xiàn)死循環(huán)的情況
2、建議不要使用hashmap進行多線程操作
8、多線程情況的意見
·1、使用concurrenthashmap類,線程安全并且效率和hashmap差不多,細粒度操作(對bucket加鎖)
2、使用Collections.synchronizedMap(new Hashmap())
3、hashtable
4、其中hashtable 和collections類的map 都是對整個map加鎖的。
9、為什么hashmap不是線程安全的
·1、擴容時,由于調(diào)整大小過程中,存儲在linkedList中的元素次序會反過來,導致多線程操作,出現(xiàn)環(huán)鏈的情況,進而引發(fā)死鎖。
2、兩個線程操作同一個hashmap時,如果一個線程更改了hashmap的結構則另一個線程調(diào)用iterator迭代時,會出現(xiàn)concurrentmodificationException (方法檢測到對象的并發(fā)修改,引發(fā)異常),產(chǎn)生fail-fast事件