? ? 再上次看了hashMap的put方法棺禾,了解了大概的流程锐借,今天再來搞搞put中的hash(key) 方法和具體計算下標的方法
1
?? ?源碼是這樣的?
static final int hash(Object key) {
int h;
return (key ==null) ?0 : (h = key.hashCode()) ^ (h >>>16);
}
相當于 ?h^h>>>16
先來了解一下這幾個運算符
????1.與運算符
????????與運算符用符號“&”表示障本,其使用規(guī)律如下:
????????兩個操作數中位都為1棋电,結果才為1栗涂,否則結果為0,
????????例如 1111 & 1110 ?結果為 1110?
????????此種運算中 得到0的概率是0.25 得到1的概率是0.75????
????2.非運算符
????????非運算符用符號“|”表示胀滚,其使用規(guī)律如下:
????????兩個位只要有一個為1趟济,那么結果就是1,否則就為0
????????例如 1111 & 1110 ?結果為 1111
????????此種運算中 得到0的概率是0.75 得到1的概率是0.25
????3.異或運算符
????????異或運算符是用符號“^”表示的咽笼,其運算規(guī)律是:
????????兩個操作數的位中顷编,相同則結果為0,不同則結果為1剑刑。
????????例如 1111 & 1110 ?結果為 0001
????????此種運算中 得到0和1的概率都是0.5?
????????接下來看h>>>16?
????????源碼中有這樣一個常量
????????static final int DEFAULT_INITIAL_CAPACITY =1 <<4;// aka 16
????????1 <<4代表 1*2的4次方
????????>>> ?則代表 無符號右移媳纬,忽略符號位,空位都以0補齊
????????h>>>16 則代表右移16位 即當key的hashCode值小于2的16次方時 h>>>16都為0
????????h^h>>>16 就是高16位和低16位的異或運算 保證hash散列的平均分布
2.計算下標
????if ((p = tab[i = (n -1) & hash]) ==null)
????????tab[i] = newNode(hash, key, value,null);
? ? tab[I =(n-1)&hash]?
? ? 此處關注的重點在于為何hashMap的初始化長度是2的4次方 以及resize()每次都是擴容為原來長度的2倍
? ? (1)我們知道 偶數的二進制最后一位是0 奇數的二進制最后一位是1 施掏,當(n-1)和hash進行&運算的時候钮惠, hash的最后一位不確定, &運算只有當都為1?七芭,結果才為1素挽,否則結果為0。那么狸驳,如果(n-1)是偶數 計算出來的值最后一位肯定為0 必然會導致我們只能使用數組長度的一半 導致資源的浪費预明,產生大量的hash沖突。而(n-1)為奇數 則會避免這個問題
????(2)還有一種說法是 當length為偶數時 可以用&代替%運算 效率高?
? ? ? ? ? ? 這點我還沒想明白 后面有時間再補充吧
? ? ? ? ? ?