物件
key和value是否允許為空
是否執行緒安全
hashmap
key和value都允許為null
否hashtable
key和value都不允許為null
是concurrenthashmap
key和value都不允許為null
是jdk1.7
超過擴容的閾值
發生碰撞
jdk1.8
超過擴容的閾值
為了通過hash值確定元素在陣列中存的位置,我們需要進行如下操作hash%length
,當時%操作比較耗時間,所以優化為hash & (length - 1)
當length為2的n次方時,hash & (length - 1) =hash % length
我們假設陣列的長度為15和16,hash碼為8和9
h & (length - 1)
hlength
index
8 & (15 - 1)
0100
1110
0100
9 & (15 - 1)
0101
1110
0100
8 & (16 - 1)
0100
1111
0100
9 & (16 - 1)
0101
1111
0101
可以看出陣列長度為15的時候,hash碼為8和9的元素被放到陣列中的同乙個位置形成鍊錶,鍵低了查詢效率,當hahs碼和15-1(1110)進行&時,最後一位永遠是0,這樣0001,0011,0101,1001,1011,0111,1101這些位置永遠不會被放置元素,這樣會導致
空間浪費大
增加了碰撞的機率,減慢查詢的效率
當陣列長度為2 n時,2 n −1的所有位都是1,如8-1=7即111,那麼進行低位&運算時,值總與原來的hash值相同,降低了碰撞的概率
由陣列+鍊錶改為陣列+鍊錶+紅黑樹,當鍊表的長度超過8時,鍊錶變為紅黑樹。
為什麼要這麼改?
我們知道鍊錶的查詢效率為o(n),而紅黑樹的查詢效率為o(logn),查詢效率變高了。
為什麼不直接用紅黑樹?
因為紅黑樹的查詢效率雖然變高了,但是插入效率變低了,如果從一開始就用紅黑樹並不合適。從概率學的角度選了乙個合適的臨界值為8
優化了hash演算法
計算元素在新陣列中位置的演算法發生了變化,新演算法通過新增位判斷oldtable[i]應該放在newtable[i]還是newtable[i+oldtable.length]
頭插法改為尾插法,擴容時鍊錶沒有發生倒置(避免形成死迴圈
)
多執行緒擴容,會讓鍊錶形成環,從而造成死迴圈
多執行緒put可能導致元素丟失
jdk1.8中死迴圈問題已經解決,元素丟失問題還存在使用concurrenthashmap
用collections.synchronizedmap(hashmap)包裝成同步集合
HashMap常見面試題
1.你知道hashmap的工作原理嗎?你知道hashmap的get 方法的工作原理嗎?hashmap基於hashing原理,我們通過put 和get 方法儲存和獲取物件。當我們將鍵值對傳遞給put 方法時,它呼叫鍵物件的hashcode 方法來計算hashcode,讓後找到bucket位置來儲存en...
HashMap常見面試題整理
花了三天時間來仔細閱讀hashmap的原始碼,期間補了下不少資料結構的知識,刷了不少相關的面試題並進行了整理 1.談一下hashmap的特性?1.hashmap儲存鍵值對實現快速訪問,允許為null。key值不可重複,若key值重複則覆蓋。2.非同步,執行緒不安全。3.底層是hash表,不保證有序 ...
常見面試題
1.get和post的區別 1 本質區別 get是向伺服器請求資料,post是向伺服器傳送資料。2 伺服器獲取值的方式 get方式提交的資料,伺服器端使用request.querystring獲取變數的值。post方式提交的資料,伺服器端使用request.form獲取資料。3 安全性 get安全效...