面試官:為什么 HashMap 的加載因子是0.75?
點(diǎn)擊上方“碼農(nóng)突圍”,馬上關(guān)注
這里是碼農(nóng)充電第一站,回復(fù)“666”,獲取一份專屬大禮包
真愛,請?jiān)O(shè)置“星標(biāo)”或點(diǎn)個(gè)“在看”

為什么HashMap需要加載因子? 解決沖突有什么方法? 為什么加載因子一定是0.75?而不是0.8,0.6?
為什么HashMap需要加載因子?
static?final?int?hash(Object?key)?{
????int?h;
????return?(key?==?null)???0?:?(h?=?key.hashCode())?^?(h?>>>?16);
}
//?AbstractMap
public?int?hashCode()?{
?????int?h?=?0;
?????Iterator>?i?=?entrySet().iterator();
?????while?(i.hasNext())
?????????h?+=?i.next().hashCode();
?????return?h;
}
加載因子 = 填入表中的元素個(gè)數(shù) / 散列表的長度
散列函數(shù)是否可以將哈希表中的數(shù)據(jù)均勻地散列? 怎么處理沖突? 哈希表的加載因子怎么選擇?
解決沖突有什么方法?
1. 開放定址法
Hi?=?(H(key)?+?di)?MOD?m,其中i=1,2,…,k(k<=m-1)
1.1 線性探查法(Linear Probing):di = 1,2,3,…,m-1
1.2 平方探測法(Quadratic Probing):di = ±12, ±22,±32,…,±k2(k≤m/2)
1.3 偽隨機(jī)探測法:di = 偽隨機(jī)數(shù)序列
這種方法建立起來的哈希表,當(dāng)沖突多的時(shí)候數(shù)據(jù)容易堆集在一起,這時(shí)候?qū)Σ檎也挥押茫?/section> 刪除結(jié)點(diǎn)的時(shí)候不能簡單將結(jié)點(diǎn)的空間置空,否則將截?cái)嘣谒钊肷⒘斜碇蟮耐x詞結(jié)點(diǎn)查找路徑。因此如果要?jiǎng)h除結(jié)點(diǎn),只能在被刪結(jié)點(diǎn)上添加刪除標(biāo)記,而不能真正刪除結(jié)點(diǎn); 如果哈希表的空間已經(jīng)滿了,還需要建立一個(gè)溢出表,來存入多出來的元素。
2. 再哈希法
Hi?=?RHi(key),?其中i=1,2,…,k
3. 建立一個(gè)公共溢出區(qū)
4. 鏈地址法(拉鏈法)
處理沖突的方式簡單,且無堆集現(xiàn)象,非同義詞絕不會(huì)發(fā)生沖突,因此平均查找長度較短; 由于拉鏈法中各鏈表上的結(jié)點(diǎn)空間是動(dòng)態(tài)申請的,所以它更適合造表前無法確定表長的情況; 刪除結(jié)點(diǎn)操作易于實(shí)現(xiàn),只要簡單地刪除鏈表上的相應(yīng)的結(jié)點(diǎn)即可。

為什么HashMap加載因子一定是0.75?而不是0.8,0.6?
臨界值 = DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR

*?Ideally,?under?random?hashCodes,?the?frequency?of
*?nodes?in?bins?follows?a?Poisson?distribution
*?(http://en.wikipedia.org/wiki/Poisson_distribution)?with?a
*?parameter?of?about?0.5?on?average?for?the?default?resizing
*?threshold?of?0.75,?although?with?a?large?variance?because?of
*?resizing?granularity.?Ignoring?variance,?the?expected
*?occurrences?of?list?size?k?are?(exp(-0.5)?*?pow(0.5,?k)?/
*?factorial(k)).?The?first?values?are:
*?0:????0.60653066
*?1:????0.30326533
*?2:????0.07581633
*?3:????0.01263606
*?4:????0.00157952
*?5:????0.00015795
*?6:????0.00001316
*?7:????0.00000094
*?8:????0.00000006
*?more:?less?than?1?in?ten?million

0:????0.60653066
1:????0.30326533
2:????0.07581633
3:????0.01263606
4:????0.00157952
5:????0.00015795
6:????0.00001316
7:????0.00000094
8:????0.00000006
那么為什么不可以是0.8或者0.6呢?
對于開放定址法,加載因子是特別重要因素,應(yīng)嚴(yán)格限制在0.7-0.8以下。超過0.8,查表時(shí)的CPU緩存不命中(cache missing)按照指數(shù)曲線上升。因此,一些采用開放定址法的hash庫,如Java的系統(tǒng)庫限制了加載因子為0.75,超過此值將resize散列表。
參考資料
泊松分布和指數(shù)分布:10分鐘教程: http://www.ruanyifeng.com/blog/2015/06/poisson-distribution.html
---END--- 重磅!碼農(nóng)突圍-技術(shù)交流群已成立 掃碼可添加碼農(nóng)突圍助手,可申請加入碼農(nóng)突圍大群和細(xì)分方向群,細(xì)分方向已涵蓋:Java、Python、機(jī)器學(xué)習(xí)、大數(shù)據(jù)、人工智能等群。 一定要備注:開發(fā)方向+地點(diǎn)+學(xué)校/公司+昵稱(如Java開發(fā)+上海+拼夕夕+猴子),根據(jù)格式備注,可更快被通過且邀請進(jìn)群 ▲長按加群 推薦閱讀
? ?那個(gè)從深圳流水線工人去Google上班程序媛,最近失業(yè)了! ???這款網(wǎng)絡(luò)排查工具,堪稱神器! ???面試官扎心一問:數(shù)據(jù)量很大,分頁查詢很慢,有什么優(yōu)化方案? ???太牛了!華中科技大學(xué)學(xué)霸,201萬頂薪簽約華為,成今年頂薪加入第一人! 網(wǎng)友:我酸了,一輩子的都到達(dá)不了 ??Java 里的 for (;;) 與 while (true),哪個(gè)更快? ?? 三年,我從語文老師到支付寶技術(shù)前端的蛻變 最近面試BAT,整理一份面試資料《Java面試BAT通關(guān)手冊》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。 獲取方式:點(diǎn)“在看”,關(guān)注公眾號并回復(fù)?BAT?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。 如有收獲,點(diǎn)個(gè)在看,誠摯感謝 明天見(??ω??)??
評論
圖片
表情

