日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

对HashMap数据结构的理解——加载因子和初始容量

發布時間:2025/3/11 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 对HashMap数据结构的理解——加载因子和初始容量 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

先看源碼:

解釋一下位移運算:

1<<4 是位移運算的表示,為十進制16
1的二進制表示:1
左移4位之后的二進制表示為B(10000) = D(16)
更簡單的計算方法就是 1<< n 等效于 1 乘以 2的 n 次方

進入正題

HashMap底層數據結構是數組+鏈表,JDK1.8中還引入了紅黑樹,當鏈表長度超過8個時,會將鏈表轉成紅黑樹,以提升其查找性能。

HashMap有兩個參數影響其性能:初始容量和加載因子。

1、HashMap的初始容量

容量是哈希表中桶的數量,初始容量只是哈希表在創建時的容量。

2、HashMap的加載因子

加載因子是哈希表在其容量自動擴容之前可以達到多滿的一種度量。

3、作用

當哈希表中的條目數超出了加載因子與當前容量的乘積時,則要對該哈希表進行擴容、rehash操作(即重建內部數據結構),擴容后的哈希表容量為原來的兩倍。

為了減少沖突的概率,當HashMap的數組長度到了一個臨界值就會觸發擴容,把所有元素rehash再放到擴容后的容器中,所以說rehash是一個非常耗時的操作。

而這個臨界值是由加載因子和當前容器的容量大小來確定:
DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR
即默認情況下是 16x0.75 =12 時,就會觸發擴容操作。

/*** Implements Map.put and related methods.** @param hash hash for key* @param key the key* @param value the value to put* @param onlyIfAbsent if true, don't change existing value* @param evict if false, the table is in creation mode.* @return previous value, or null if none*/final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {Node<K,V> e; K k;if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();afterNodeInsertion(evict);return null;}

4、面試高頻:為什么加載因子初始化是0.75呢?

  • 也是一個綜合考慮,如果設置過小如0.5,HashMap 每 put 少量的數據,都要進行一次擴容,而擴容操作會消耗大量的性能。使得空間利用率很低,同時提高了rehash(重建內部數據結構)操作的次數。
  • 如果設置過大的話,比如設成1,容量還是16,假設現在數組上已經占用了15個,再要put數據進來,計算數組 index 時,發生 hash碰撞 的概率將達到15/16,這違背了 HashMap 減少 hash碰撞 的原則。同時,這樣會減少空間開銷,提高空間利用率,但同時會增加查詢時間的成本。
  • 因此,選擇0.75作為默認的加載因子,完全是時間和空間成本上尋求折中的選擇。
  • 在設置初始容量時應該考慮到映射中所需的條目數及其加載因子,以便最大限度地減少rehash操作次數,所以,一般在使用HashMap時建議根據預估值設置初始容量,減少擴容操作。

4、面試高頻:為什么初始容量是16

當容量為2的冪次方時,源碼中 n -1 對應的二進制數全為1,這樣才能保證它和 key 的 hashcode 做&運算后,能夠均勻分布,這樣才能減少hash碰撞的次數。至于默認值為什么是16,而不是2 、4、8,或者32、64、1024等,應該就是個折中處理,過小會導致放不下幾個元素,就要進行擴容了,而擴容是一個很消耗性能的操作。取值過大的話,無疑會浪費更多的內存空間。因此在日常開發中,如果可以預估HashMap會存入節點的數量,則應該在初始化時,指定其容量。

參考原文:
HashMap容量和負載因子:https://blog.csdn.net/ye17186/article/details/88876417
HashMap中的初始容量和加載因子:https://blog.csdn.net/weixin_44723496/article/details/112387738

總結

以上是生活随笔為你收集整理的对HashMap数据结构的理解——加载因子和初始容量的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。