1、HashMap的初始長度是怎么計算的?
默認(rèn)是這么實現(xiàn)的
給定一個數(shù),例如12, 先往右移1位,或上之后再移2位,或之后再移4位等等,一直移到16位叫返回給定目標(biāo)容量的二次冪。
2、 HashMap是怎么計算的
高16位和低16位 先做異或運算 再與 1111 做 或運算
3、 hash插入一條數(shù)據(jù)
先通過hash函數(shù),計算索引,找到數(shù)組的位置(如果為空直接放入,若果不為空,遍歷整個鏈表,這里分為兩種,如果有值直接復(fù)寫,如果沒有值,則用頭插法)
4、 擴(kuò)容是怎么實現(xiàn)的
先new一個兩倍大小的數(shù)組,遍歷舊數(shù)組,讓item變成游離態(tài),直接放入新的數(shù)組,(1??沒有值直接復(fù)制,2??有值直接變成頭結(jié)點,之前的節(jié)點變成子節(jié)點)
5、 HashMap的原理,內(nèi)部數(shù)據(jù)結(jié)構(gòu)?
底層使用哈希表(數(shù)組 + 鏈表), 當(dāng)鏈表過長會將鏈表轉(zhuǎn)成紅黑樹以實現(xiàn)O(logn)時間復(fù)雜度內(nèi)查找
6、 講一下HashMap中put方法過程?
1、對key求Hash值,然后再計算下標(biāo)
2、如果沒有碰撞,直接放入桶中
3、如果碰撞了,以鏈表的方式鏈接到后面
4、 如果鏈表長度超過閾值(TREEIFY_THRESHOLD == 8), 就把鏈表轉(zhuǎn)成紅黑樹
5、 如果節(jié)點已經(jīng)存在就替換舊值
6、 如果桶滿了(容量*加載因子),就需要resize
7、 HashMap中hash函數(shù)怎么實現(xiàn)的?還有哪些hash的實現(xiàn)方式?
1、 高16bit不變, 低16bit和高16bit做了一個異或
2、 (n-1) & hash --> 得到下標(biāo)
8、 HashMap怎么解決沖突,講一下擴(kuò)容過程,假如一個值在原數(shù)組中,現(xiàn)在移動了新數(shù)組,位置肯定改變了,那是怎么定位到現(xiàn)在這個值新數(shù)組中的位置?
1、 將新節(jié)點加到鏈表后
2、 容量擴(kuò)充為原來的兩倍,然后對每個節(jié)點重新計算哈希值
3、 這個值只可能在兩個地方,一個是原下標(biāo)的位置,另一種是在下標(biāo)為<原下標(biāo)+原容量>的位置
9、 拋開HashMap,hash沖突有哪些解決辦法?
開放定址,鏈地址法
10、 針對HashMap中某個Entry鏈太長,查找的時間復(fù)雜度可能達(dá)到O(n), 怎么優(yōu)化?
將鏈表轉(zhuǎn)為紅黑樹,JDK1.8已經(jīng)實現(xiàn)了
11、HashMap的缺點
線程不是安全的,假如一個線程遍歷10w次,線程高并發(fā) 容易出錯,直接拋異常