您好,登錄后才能下訂單哦!
本篇內容主要講解“Java HashMap的大小是多少”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Java HashMap的大小是多少”吧!
HashMap 的默認大小是 16,這個默認值是可以設置的。如果事先知道具體的例子,可以修改默認初始大小,減少動態擴容的次數,提高性能。修改默認初始大小的值時,比如你設置了 500,那么不會真就使用 500 這個值,而可能會使用 512 這種是 2 的冪的值。
為什么要設置是 2 的冪的值?這個跟下面的 index 的值計算有關,請看第 4 點。
最大的裝載因子為 0.75,當裝載因子超過這個值是就會擴容,每次擴容都會擴容為原來的兩倍大小。
那么為什么裝載因子是 0.75 呢?經研究顯示,負載因子是0.75的時候,空間利用率比較高,而且避免了相當多的 Hash 沖突,使得底層的鏈表或者是紅黑樹的高度比較低,提升了空間效率。
為啥是擴容為原來的兩倍呢?這個具體請看第 4 點。
采用鏈表法來解決沖突,之后再 JDK1.8 中引入了紅黑數,主要鏈表長度太長(默認超過8)時,鏈表就轉換為紅黑樹。當少于 6 時,又將紅黑樹轉換為鏈表,因為紅黑樹要維護平衡,比起鏈表性能上的優勢并不會特別明顯。
那么為什么在少于 6 的時候而不是 8 的時候才將紅黑樹轉換為鏈表呢?假設設計成大于 8 時鏈表轉換為紅黑樹,小于 8 的時候又轉換為鏈表。如果一個 hashmap 不停的插入、刪除。hashmap 中的個數不停地在 8 徘徊,那么就會頻繁的發生鏈表和紅黑樹之間轉換,效率非常低。因此,6 和 8 之間來一個過渡值可以減緩這種情況造成的影響。
散列值的獲取分兩步走:
// 1. hash 值的計算
static final int hash(Object key) {
int hash;
return key == null ? 0 : (hash = key.hashCode()) ^ hash >>> 16;
}
// 2. 插入/查找的時候,計算 key 應該被映射到散列表的什么位置
int index = hash(key) & (capacity - 1)
其中方法 hashcode() 返回的是 Java 對象的 hash_code,這是一個 int 類型的值(32 位)。那么為什么在拿到這個值之后,還需要將自己右移 16 位與自己進行異或呢?因為容量較小的時候,在計算 index 那邊,真正用到的其實就只有低幾位,假如不融合高低位,那么假設 hashcode() 返回的值都是高位的變動的話,那么很容易造成散列的值都是同一個。但是,假如將高位和低位融合之后,高位的數據變動會最終影響到 index 的變換,所以依然可以保持散列的隨機性。
那么在計算 index 的時候,為什么不使用 hash(key) % capacity
呢?這是因為移位運算相比取余運算會更快。那么為什么 hash(key) & (capacity - 1) 也可以呢?這是因為在 B 是 2 的冪情況下:A % B = A & (B - 1)。如果 A 和 B 進行取余,其實相當于把 A 那些不能被 B 整除的部分保留下來。從二進制的方式來看,其實就是把 A 的低位給保留了下來。B-1 相當于一個“低位掩碼”,而與的操作結果就是散列值的高位全部置為 0 ,只保留低位,而低位正好是取余之后的值。我們取個例子,A = 24,B =16,那么 A%B=8,從二進制角度來看 A =11000 ,B = 10000。A 中不能被 B 整除的部分其實就是 1000 這個部分。接下去,我們需要將這部分保留下來的話,其實就是使用 01111 這個掩碼并跟 A 進行與操作,即可將1000 保留下來,作為 index 的值。而 01111 這個值又等于 B-1。所以 A &(B-1)= A%B。但是這個前提是 B 的容量是 2 的冪,那么如何保證呢?我們可以看到,在設置初始大小的時候,無論你設置了多少,都會被轉換為 2 的冪的一個數。之外,擴容的時候也是按照 2 倍進行擴容的。所以 B 的值是 2 的冪是沒問題的。
到此,相信大家對“Java HashMap的大小是多少”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。