hashmap為什麼要有負載因子?

時間 2021-06-09 00:30:02

1樓:愚公要移山

對於HashMap的研究,我之前一直停留在考慮原始碼是如何實現的,現在當我重新再來看的時候,才發現,系統預設的各種引數值,才是HashMap的精華所在。

負載因子是和擴容機制有關的,意思是如果當前容器的容量,達到了我們設定的最大值,就要開始執行擴容操作。舉個例子來解釋,避免小白聽不懂:

比如說當前的容器容量是16,負載因子是0.75,16*0.75=12,也就是說,當容量達到了12的時候就會進行擴容操作。

他的作用很簡單,相當於是乙個擴容機制的閾值。當超過了這個閾值,就會觸發擴容機制。HashMap原始碼已經為我們預設指定了負載因子是0.

75。public class HashMap extends AbstractMap

implements Map, Cloneable, Serializable

我擷取了部分原始碼,從這裡可以看出,系統預設的負載因子值就是0.75,而且我們還可以在構造方法中去指定。下面我們就正式來分析一下為什麼是預設的0.75。

我們在考慮HashMap的時候,首先要想到的是HashMap只是乙個資料結構,既然是資料結構最主要的就是節省時間和空間。負載因子的作用肯定也是節省時間和空間。為什麼節省呢?

我們考慮兩種極端情況。

1、負載因子是1.0

我們先看HashMap的底層資料結構

我們的資料一開始是儲存在陣列裡面的,當發生了Hash碰撞的時候,就是在這個資料節點上,生出乙個鍊錶,當鍊表長度達到一定長度的時候,就會把鍊錶轉化為紅黑樹。

當負載因子是1.0的時候,也就意味著,只有當陣列的8個值(這個圖表示了8個)全部填充了,才會發生擴容。這就帶來了很大的問題,因為Hash衝突時避免不了的。

當負載因子是1.0的時候,意味著會出現大量的Hash的衝突,底層的紅黑樹變得異常複雜。對於查詢效率極其不利。

這種情況就是犧牲了時間來保證空間的利用率。

因此一句話總結就是負載因子過大,雖然空間利用率上去了,但是時間效率降低了。

2、負載因子是0.5

負載因子是0.5的時候,這也就意味著,當陣列中的元素達到了一半就開始擴容,既然填充的元素少了,Hash衝突也會減少,那麼底層的鍊錶長度或者是紅黑樹的高度就會降低。查詢效率就會增加。

但是,兄弟們,這時候空間利用率就會大大的降低,原本儲存1M的資料,現在就意味著需要2M的空間。

一句話總結就是負載因子太小,雖然時間效率提公升了,但是空間利用率降低了。

3、負載因子0.75

經過前面的分析,基本上為什麼是0.75的答案也就出來了,這是時間和空間的權衡。當然這個答案不是我自己想出來的。答案就在原始碼上,我們可以看看:

/* As a general rule, the default load factor (.75) offers a good

* tradeoff between time and space costs. Higher values decrease the

* space overhead but increase the lookup cost (reflected in most of

* the operations of the HashMap class, including

* get and put). The expected number of entries in

* the map and its load factor should be taken into account when

* setting its initial capacity, so as to minimize the number of

* rehash operations. If the initial capacity is greater than the

* maximum number of entries divided by the load factor, no rehash

* operations will ever occur.*/

大致意思就是說負載因子是0.75的時候,空間利用率比較高,而且避免了相當多的Hash衝突,使得底層的鍊錶或者是紅黑樹的高度比較低,提公升了空間效率。

OK,寫到這答案基本上就出來了,一句話能總結的寫成了一篇文章。如有問題,還請批評指正。

2樓:勉強

這話說的。。。

沒有擴容的例子:

要是有1w個資料往10個桶裡面放,平均下來每個桶是1000個資料,就算在jdk8中每個桶預設超過8個會給你轉成紅黑樹,那你找乙個元素的平均時間也是也是log(以2為底)1000。

反過來,如果擴了容。過程同上,但是平均時間會大大縮短。

還有誰說12就會擴容?這只是預設情況。

,盡量避免擴容情況(會產生額外的代價)的同時也不能特別浪費記憶體

為什麼 HashMap 中的load factor在各個語言的實現中都在 0 6 0 8 之間?

乾貨滿滿張雜湊 首先,這個基於乙個假設,那麼就是當乙個事件發生的概率大於 0.5,那麼這件事就是很可能發生的。然後,假設當前有 s 個桶,那麼每次放入乙個元素進入某乙個桶的概率就是 放入了第 n 個元素,那麼,某乙個桶元素個數為e的概率,根據二項式分布就是 將e 0代入,得出 讓這個概率大於 0.5...

java中hashmap為什麼key的值不一樣呼叫hashcode的hash值為什麼相同?

Intopass 因為KEY的 容量 有可能超過雜湊值 int型別 的容量,你從乙個大範圍對映到小範圍必然不可能保證一對一,只能是多對一。 hashcode的目的是實現對若干物件分批次,key的值不一樣 意味著不同的key之間呼叫equals 方法返回false。hashcode分批次的目的是,把大...

為什麼負載是指電流?

正常情況下,直流電源供電分為恆壓型和恆流型兩類。恆壓型電源,負載功率 簡稱負載 大小跟負載電流成正比 恆流型電源,負載功率跟負載電流的平方成正比。因此在說到負載大小的時候,往往可以用電流大小來定性描述。 減速電機 魏先生 電機裝成成品後,它的效能曲線就定型了。如圖P巔峰以前,電機是做正功。P巔峰以後...