HashMap常見問題整理

2021-09-28 16:20:00 字數 3119 閱讀 4200

二、hashmap在什麼條件下擴容

三、hashmap的get/put的過程

知道hashmap中get元素的過程是什麼樣嗎

你還知道哪些hash演算法?

說說string中hashcode的實現?(此題頻率很高)

四、為什麼hashmap的在鍊錶元素數量超過8時改為紅黑樹

五、hashmap的併發問題

六、你一般用什麼作為hashmap的key

hashmap採用entry陣列來儲存key-value對,每乙個鍵值對組成了乙個entry實體,entry類實際上是乙個單向的鍊錶結構,它具有next指標,可以連線下乙個entry實體。

只是在jdk1.8中,鍊錶長度大於8的時候,鍊錶會轉成紅黑樹!

陣列是用來確定桶的位置,利用元素的key的hash值對陣列長度取模得到.

鍊錶是用來解決hash衝突問題,當出現hash值一樣的情形,就在陣列上的對應位置形成一條鍊錶

答案很明顯,必須是可以的。

既然是可以的,為什麼hashmap不用linkedlist,而選用陣列?

因為用陣列效率最高!

在hashmap中,定位桶的位置是利用元素的key的雜湊值對陣列長度取模得到。此時,我們已得到桶的位置。顯然陣列的查詢效率比linkedlist大。

因為採用基本陣列結構,擴容機制可以自己定義,hashmap中陣列擴容剛好是2的次冪,在做取模運算的效率高。

而arraylist的擴容機制是1.5倍擴容,那arraylist為什麼是1.5倍擴容這就不在本文說明了。

如果bucket滿了(超過load factor*current capacity),就要resize。

load factor為0.75,為了最大程度避免雜湊衝突

current capacity為當前陣列大小。

hashmap為了訪問高效,要盡量較少碰撞,就是要盡量把資料分配均勻,每個鍊錶長度大致相同,這個實現就在把資料存到哪個鍊錶中的演算法;這個演算法實際就是取模,hash%length。

但是,大家都知道這種運算不如位移運算快。

因此,原始碼中做了優化hash&(length-1)。

也就是說hash%length==hash&(length-1)

位運算比較高效,當b為2的n次方時,有如下替換公式:

a % b = a & (b-1)(b=2n)

即:a % 2n = a & (2n-1)

hashmap這麼做,只是為了降低hash衝突的機率。

比如,當我們的length為16的時候,雜湊碼(字串「abcabcabcabcabc」的key對應的雜湊碼)對(16-1)與操作,對於多個key生成的hashcode,只要雜湊碼的後4位為0,不論不論高位怎麼變化,最終的結果均為0。

如下圖所示

而加上高16位異或低16位的「擾動函式」後,結果如下

對key的hashcode()做hash運算,計算index;

如果沒碰撞直接放到bucket裡;

如果碰撞了,以鍊錶的形式存在buckets後;

如果碰撞導致鍊錶過長(大於等於treeify_threshold),就把鍊錶轉換成紅黑樹(jdk1.8中的改動);

如果節點已經存在就替換old value(保證key的唯一性)

如果bucket滿了(超過load factor*current capacity),就要resize。

對key的hashcode()做hash運算,計算index;

如果在bucket裡的第乙個節點裡直接命中,則直接返回;

如果有衝突,則通過key.equals(k)去查詢對應的entry;

若為樹,則在樹中通過key.equals(k)查詢,o(logn);

若為鍊錶,則在鍊錶中通過key.equals(k)查詢,o(n)。

先說一下hash演算法幹嘛的,hash函式是指把乙個大範圍對映到乙個小範圍。把大範圍對映到乙個小範圍的目的往往是為了節省空間,使得資料容易儲存。

比較出名的有murmurhash、md4、md5等等

public

inthashcode()

hash = h;

}return h;

}

string類中的hashcode計算方法還是比較簡單的,就是以31為權,每一位為字元的ascii值進行運算,用自然溢位來等效取模。

主要是因為31是乙個奇質數,所以31i=32i-i=(i<<5)-i,這種位移與減法結合的計算相比一般的運算快很多。

最後一條是重點,因為最後一條的變動,hashmap在1.8中,不會在出現死迴圈問題。

因為紅黑樹需要進行左旋,右旋,變色這些操作來保持平衡,而單鏈表不需要。

當元素小於8個當時候,此時做查詢操作,鍊錶結構已經能保證查詢效能。當元素大於8個的時候,此時需要紅黑樹來加快查詢速度,但是新增節點的效率變慢了。

因此,如果一開始就用紅黑樹結構,元素太少,新增效率又比較慢,無疑這是浪費效能的。

可以。但是二叉查詢樹在特殊情況下會變成一條線性結構(這就跟原來使用鍊錶結構一樣了,造成很深的問題),遍歷查詢會非常慢。

為6的時候退轉為鍊錶。中間有個差值7可以防止鍊錶和樹之間頻繁的轉換。假設一下,如果設計成煉表個數超過8則鍊錶轉換成樹結構,鍊錶個數小於8則樹結構轉換成鍊錶,如果乙個hashmap不停的插入、刪除元素,鍊錶個數在8左右徘徊,就會頻繁的發生樹轉鍊錶、鍊錶轉樹,效率會很低。

在jdk1.8中,死迴圈問題已經解決。其他兩個問題還是存在。

可以,key為null的時候,hash演算法最後的值以0來計算,也就是放在陣列的第乙個位置。

一般用integer、string這種不可變類當hashmap當key,而且string最為常用。

hashcode可能發生改變,導致put進去的值,無法get出。

針對問題一,記住下面四個原則

hashmap常見問題

hashmap可以接受null鍵值和值,而hashtable則不能 hashmap是非synchronized hashmap很快 以及hashmap儲存的是鍵值對 hashmap的工作原理 hashmap是基於hashing的原理,我們使用put key,value 儲存物件到hashmap中,使...

AIX常見問題整理

問 怎樣設定可以是普通使用者不能su成root?答 itty user change show characteristics of a user root another user can su to user?false aixtoolbox installp ppc rpm.rte安裝時,以r...

IOS常見問題整理

nsallowsarbitraryloads 2 ios應用啟動時不佔滿全屏,上下有黑邊 原因是沒有retina4對應的啟動,解決方法很簡單,就是把retina4對應的給補上就只可以了 設定 launch images source 集 ios 8以前啟動頁用,8以後的用xib檔案 3 html i...