假設一段**:
hashmap
map =
newhashmap
();map.
put(「張三」, 「測試資料」)
;map.
put(「李四」, 「測試資料」)
;
對張三這個key,計算出hash值,對hash值進行取模處理,定位到陣列裡的乙個元素中去
[<>, <>, <>, 《張三, 測試資料》, 《李四, 測試資料》, <>, <>, <>]
如:
map.
put(「張三」, 「測試資料」)
;
對」張三」這個key計算它的hash值,是有一定優化的:
static
final
inthash
(object key)
先拿到key的hashcode,再與二進位制右移16位後的值進行異或運算;
定址演算法的優化:
(n - 1) & hash
陣列的長度減1後,與hash值的二進位制進行與運算,得到陣列中的乙個位置;
hash演算法的優化可以在一定程度上避免hash衝突;
put的時候,當兩個key或者多個key,定位出的在陣列中的位置還是一樣的,就會出現hash碰撞的情況;
這時候單單採用陣列就不能解決問題了,會在陣列中的該位置掛上乙個鍊錶,在鍊錶裡面放入多個元素,讓多個key-value對同時放在陣列的乙個位置裡,從而有效解決了hash衝突的問題。
get的時候,如果定位到陣列裡,發現這個位置掛了乙個鍊錶,則只需遍歷這個鍊錶,從中找到自己要找的那個key-value對即可。
假設你的鍊錶長度過長時,可能會導致遍歷鍊錶的效能比較差,
解決辦法是當鍊錶的長度達到一定的上限時,就會把鍊錶轉換為紅黑樹,好處在於遍歷紅黑樹查詢元素的時間複雜度為o(logn),效能相較於鍊錶會有所提高。
由於hashmap底層是乙個陣列,所以當這個陣列滿了以後,就不可避免地要涉及到陣列擴容的問題,變成乙個更大的陣列,讓你在裡面可以放更多的元素;
預設的擴容機制是2倍擴容;
進行擴容之後,要進行rehash,就是把擴容前的陣列中的元素重新定址定位到擴容後新的陣列位置上去。
HashMap底層資料結構
jdk1.8之前 陣列 鍊錶 jdk1.8之後 陣列 鍊錶 紅黑樹 陣列的時間複雜度 o 1 鍊錶的時間複雜度 o n 紅黑樹時間複雜度 o logn 為什麼使用陣列?陣列的的讀 寫速度快。查詢快,增刪慢 為什麼使用鍊錶?為了避免資料的key產生雜湊碰撞後將原有的陣列下標對應的值直接替換。查詢慢,增...
初步了解HashMap底層資料結構
本文主要講述hashmap的一些簡單原理,如果講的不好,可以說出來,讓我改正本文。說到hashmap的資料結構,就需要說到資料結構中的陣列和單鏈表結構,因為hashmap的底層就是陣列和鍊錶,不過這是jdk1.7版本的,1.8版本後加入了紅黑樹。下面先介紹一些這些資料結構。陣列儲存區間是連續的,占用...
索引的底層資料結構
索引的底層資料結構有 1 樹tree,準確的說是b 樹 2 hash 時間複雜度對比 hash的時間o 1 tree的o logn 為什麼索引採用b 樹,而不採用hash這種結構?hash這種結構對與獲取單條記錄時的查詢效率是要比b 樹效率要高的,但是對與資料的範圍查詢效率就很低,特別是對於資料量大...