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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

longtext长度为0是什么意思_为什么 HashMap 中链表长度大于 8 才转化为红黑树?

發布時間:2023/12/2 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 longtext长度为0是什么意思_为什么 HashMap 中链表长度大于 8 才转化为红黑树? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java 中的 HashMap 采用鏈表法來解決哈希沖突(HashMap 原理),即具有相同桶下標的鍵值對使用一個鏈表儲存。當鏈表變長時,查找和添加(需要確定 key 是否已經存在)都需要遍歷這個鏈表,速度會變慢。JDK 1.8 后加入了鏈表轉換為紅黑樹的機制,但是紅黑樹的轉換并不是一個廉價的操作,只有當鏈表長度大于等于 TREEIFY_THRESHOLD 才會 treeify。

/*** The bin count threshold for using a tree rather than list for a* bin. Bins are converted to trees when adding an element to a* bin with at least this many nodes. The value must be greater* than 2 and should be at least 8 to mesh with assumptions in* tree removal about conversion back to plain bins upon* shrinkage.*/static final int TREEIFY_THRESHOLD = 8;

TREEIFY_THRESHOLD 默認為 8,putVal() 源碼如下:

if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);

實際上并不是只要鏈表長度大于 8 就會 treeify。當 table.length(桶的個數)小于 MIN_TREEIFY_CAPACITY 時會優先擴容而不是轉換為紅黑樹。

/*** The smallest table capacity for which bins may be treeified.* (Otherwise the table is resized if too many nodes in a bin.)* Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts* between resizing and treeification thresholds.*/static final int MIN_TREEIFY_CAPACITY = 64;

MIN_TREEIFY_CAPACITY 默認為 64,treeifyBin() 源碼大致是這樣:

final void treeifyBin(Node<K,V>[] tab, int hash) {int n, index; Node<K,V> e;if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) // 大小不夠,優先擴容resize();else if ((e = tab[index = (n - 1) & hash]) != null) {// ...}}

為什么是 8 ?

TREEIFY_THRESHOLD 的默認值 8 是如何確定的呢?源碼中的注解其實給出了答案:

Because TreeNodes are about twice the size of regular nodes, we use them only when bins contain enough nodes to warrant use (see TREEIFY_THRESHOLD). And when they become too small (due to removal or resizing) they are converted back to plain bins. In usages with well-distributed user hashCodes, tree bins are rarely used. Ideally, under random hashCodes, the frequency of nodes in bins follows a 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:

treeify 過程會把原本的 Node 對象轉化為 TreeNode 對象,而 TreeNode 大小是 Node 的兩倍;除去內存的損耗,treeify 本身也是一個耗時的過程,并且在紅黑樹節點數小于等于 UNTREEIFY_THRESHOLD(默認為 6)時,紅黑樹又會重新轉換為鏈表,如果出現頻繁的相互轉化,這是一筆不小的開銷。

所以我們需要確定一個 k 值,鏈表長度大于等于 k 時,會轉化為紅黑樹。k 不能太大,因為鏈表的長度過大會影響插入和查找效率;k 也不能太小,treeify 并不是一個廉價的操作,我們希望鏈表長度大于等于 k 的概率要足夠小,這樣就可以盡量避免 treeify。

鏈表長度為 k 的概率就是出現 k 個鍵值對都在同一個桶中的概率,假設 table 的長度為 m,也就是有 m 個桶,一個鍵值對落入每一個桶都是等概率的,求不同 k 對應的概率就是標準的泊松分布問題:

其中

, 由于等概率,所以 ,關鍵在于求 ,也就是鍵值對的個數。

通常情況下 HashMap 都是要經歷擴容過程的,擴容后 table 的長度是原來的兩倍,不妨以這個角度來考慮鍵值對的個數。我們知道當鍵值對個數大于等于加載因子(默認 0.75f)和當前 table 長度的乘積時,會發生擴容,所以剛剛完成擴容時:

要發生下一次擴容時:

求均值:

最后求得:

帶入式(1),得出下表:

  • X = 0: P = 0.60653066
  • X = 1: P = 0.30326533
  • X = 2: P = 0.07581633
  • X = 3: P = 0.01263606
  • X = 4: P = 0.00157952
  • X = 5: P = 0.00015795
  • X = 6: P = 0.00001316
  • X = 7: P = 0.00000094
  • X = 8: P = 0.00000006
  • X > 8: P less than 1 in ten million

可以看到 8 個鍵值對同時存在于同一個桶的概率只有 0.00000006,比 8 大的概率更是小于千萬分之一,就它了!

總結

以上是生活随笔為你收集整理的longtext长度为0是什么意思_为什么 HashMap 中链表长度大于 8 才转化为红黑树?的全部內容,希望文章能夠幫你解決所遇到的問題。

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