hashmap之位運算

2021-10-25 07:16:27 字數 1657 閱讀 8874

通過以下**開始

static

final

inttablesizefor

(int cap)

|=(或等於):這個符號比較少見,但是「+=」應該都見過,看到這你應該明白了。例如:a |= b ,可以轉成:a = a | b。

假設 n 的值為 0010 0001,則該計算如下圖:

hashmap 的容量必須是 2 的 n 次方,這是為什麼?

計算索引位置的公式為:(n - 1) & hash,當 n 為 2 的 n 次方時,n - 1 為低位全是 1 的值,此時任何值跟 n - 1 進行 & 運算的結果為該值的低 n 位,達到了和取模同樣的效果,實現了均勻分布。實際上,這個設計就是基於公式:x mod 2^n = x & (2^n - 1),因為 & 運算比 mod 具有更高的效率。

如下圖,當 n 不為 2 的 n 次方時,hash 衝突的概率明顯增大。

^運算子跟 | 類似,但有一點不同的是 如果兩個操作位都為1的話,結果產生0

0 1 0 0 0 0 0 1

0 1 0 1 1 0 1 0

產生 0 0 0 1 1 0 1 1

通過hash算法定位元素在陣列中的位置

static

final

inthash

(object key)

// 真正定位到元素在陣列中的位置

n = tab.length;

i =(n -1)

& hash

整個過程本質上就是三步:拿到 key 的 hashcode 值

將 hashcode 的高位參與運算,重新計算 hash 值

將計算出來的 hash 值與 (table.length - 1) 進行 & 運算

x mod 2^n=x&(2 ^ n-1)

那在什麼時候用鍊錶?什麼時候用紅黑樹?

對於插入,預設情況下是使用鍊錶節點。當同乙個索引位置的節點在新增後達到9個(閾值8):如果此時陣列長度大於等於 64,則會觸發鍊錶節點轉紅黑樹節點(treeifybin);而如果陣列長度小於64,則不會觸發鍊錶轉紅黑樹,而是會進行擴容,因為此時的資料量還比較小。

對於移除,當同乙個索引位置的節點在移除後達到 6 個,並且該索引位置的節點為紅黑樹節點,會觸發紅黑樹節點轉鍊錶節點(untreeify)

如果我們設定節點多於8個轉紅黑樹,少於8個就馬上轉鍊錶,當節點個數在8徘徊時,就會頻繁進行紅黑樹和鍊錶的轉換,造成效能的損耗

任何數對乙個指定的數字進行取模,結果總會落在[0,指定的數字之間]。。。

HashMap位運算你可知一二

我們平時在寫 過程中用的位運算操作比較少,因為我們更關注於可讀性而不是效能,如果為了效能而使用較多的位運算,我想我們的同事會瘋掉。但在框架里位運算卻非常常見,因為框架的效能是我們關注的點。下面就來一起回顧一下常見的位運算操作 左移運算子,num 1,相當於num乘以2 低位補0 表示右移,如果該數為...

異或運算 HashMap位運算你可知一二

我們平時在寫 過程中用的位運算操作比較少,因為我們更關注於可讀性而不是效能,如果為了效能而使用較多的位運算,我想我們的同事會瘋掉。但在框架里位運算卻非常常見,因為框架的效能是我們關注的點。下面就來一起回顧一下常見的位運算操作 左移運算子,num 1,相當於num乘以2 低位補0 表示右移,如果該數為...

LeetCode之位運算

public intadd int a,int b return a 劍指offer 64 求1 2 n 難度 中等 求 1 2 n 要求不能使用乘除法 for while if else switch case等關鍵字及條件判斷語句 a?b c 題解 用遞迴的方法的 public intsumnu...