面试必备:HashMap底层数据结构?jdk1.8算法优化,hash冲突,扩容等问题
面試必備系列不會長篇理論求證,直接上答案,僅供參考,不喜勿噴。
1、能說說HashMap的底層原理嗎?
HashMap<String,String>?map?=?new?HashMap<String,String>();?map.put(“key”,”value”);?
[<key1,value1>,<key2,value2>,<key3,value3>]?
HashMap底層實現是數組+鏈表,用來存儲<key,value>形式的數據,當我們調用put(key,value)時,首先會通過hash(key) 來獲取key的hash值,hash值對數組長度進行取模運算,定位到數組的一個存儲位置 bucket,如果bucket沒有發生沖突的話則直接放入數組,發生沖突的話則以鏈表的形式存儲,jdk1.8之后引入了紅黑樹,鏈表的長度超過8之后會使用紅黑樹,小于6之后則又轉換回來。
如下2、3條皆為第1條的補充,預防面試官細問。
2、jdk1.8中對hash算法和尋址算法的優化
jdk1.8中對hash算法進行了優化,之前在對key進行hash(key)計算時,采用的是取模運算,即第1條提到的,而優化后采用的是尋址算法,即:(n-1) & hash 『n為數組長度』
為什么要使用尋址算法呢?首先 「hash & (n-1)」 效果跟 hash 對 n 取模的效果是一樣的, 但是『&』與運算的性能要優于 hash 對 n 取模。
3、hash沖突?怎么解決?
當我們put<key,value>時,首先通過hash(key)計算得到的hash值,再通過『&』與運算之后,得到了數組存儲位置bucket,但此時出現了兩個不同的key卻計算出相等的bucket,舉個例子:
數組A[0]位置計算出存放<張三,我是張三>數據,而在put<李四,我是李四>數據時,也計算為存放在A[0]位置,一個位置想存放兩個數據?這就出現hash沖突了,怎么處理呢?
JDK是這樣處理的,它會在這個位置(A[0])掛一個鏈表,這個鏈表表里面存放出現沖突的數據,即:讓多個<key,value>數據同時放在數組的一個位置里。
get(key)時怎么取呢?當我們調用get(key)定位到數組位置時,如果發現這個位置掛載的是一個鏈表,那么就遍歷鏈表,從里面找到自己想要的那個<key,value>數據。
格外補充:這個地方,在JDK1.8之后引入了紅黑樹的概念,首先我們看一下為啥要引入紅黑樹,如果沒有引入紅黑樹,當數組掛載的鏈表達到一定長度之后,查詢是非常耗時的,性能比較差,時間復雜度為:O(n)「讀作:偶en」。
JDK1.8的優化就是,當鏈表的長度發到了一定長度后(8)會自動轉換為紅黑樹,遍歷一棵紅黑樹查找一個元素的時間復雜度為:O(logn)「讀作:偶,老個en」,性能相對鏈表要高一些。
簡單總結一下:
出現hash沖突的原因?兩個不同的key計算出相同的數組存放位置;
初期是怎么解決的?在出現數組沖突的位置掛一個鏈表,實現存放多個數據。
JDK1.8的優化?當數組長度達到一定值后自動轉換為紅黑樹,降低時間復雜度。
4、HashMap是如何擴容的?
HashMap底層是一個數組,當數組滿了之后,他會自動進行2倍擴容,用于盛放更多的數據。
比如,本來數組默認長度=16,擴容后*2=32。
擴容后還有一步操作:rehash,重新對每個hash值進行尋址,也就是用每個hash值跟新的數組長度 n-1 進行『&』與運算操作。
補充:擴容之后的與運算可能會導致之前的發生hash沖突的元素不再發生沖突。
博客地址:https://www.cnblogs.com/niceyoo
總結
以上是生活随笔為你收集整理的面试必备:HashMap底层数据结构?jdk1.8算法优化,hash冲突,扩容等问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言版RPG角色生成器
- 下一篇: Ubuntu 配置swftools(Ub