ConcurrentHashMap之tableSizeFor()方法透析(位運算運用)


 
ConcurrentHashMap和HashMap有如下方法
inttableSizeFor(int c)
//功能:輸入低於最大容量的數c,返回大於等於且最接近c的2的冪次數。
源碼:
 
private static final int MAXIMUM_CAPACITY = 1 << 30;
 
private static final int tableSizeFor(int c) {
    int n = c - 1;
    n |= n >>> 1;  
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

 

解釋/總結1:符號>>:右移n位相當於除以2的n次方。符號<<:左移n位就相當於乘以2的n次方。 >>>無符號右移:"零擴展",無論正負,左邊都補0。|符號,按位或,使用二進制計算:0|1=1,0|0=0,1|1=1
2:設c=010001101,即141.
執行:先減1,n=140--轉為2進制---010001100  
    n |= n >>> 1------無符號右移一位,左邊補0
    001000110 |       |操作
    010001100   
->n=011001110
    n |= n >>> 2------同上
    011001110 | 
    000110011     
->n=011111111=255
最高位1后面已經均為1, 后面再執行|操作n不會發生變化了,
最后n=255,返回n+1即256。可以看出該算法通過幾次無符號右移和|操作會讓最高位的1后面的位全變為1。
3:在使用位運算之前減1是必要的,否則對於c=16,最后就會得到32.實際需求應當返回16.
4:為什么最后寫到n|n >>> 16?我們知道int范圍在-2^31~2^31-1,因此對於int最大的2次冪數為2^30,這也就是MAXIMUM_CAPACITY的值。c超過這個值就會返回MAXIMUM_CAPACITY。
而這邊代碼中一共右移了1+2+4+8+16=31位,因此可以保證高位1以下的低位都會變成1.
5 :如果c是負數,那么結果如何
int c=-100;
c|= c >>> 1;
System.out.println( c );
c|= c >>> 2;
System.out.println( c );
c|= c >>> 4;
System.out.println( c );
c|= c >>> 8;
System.out.println( c );
結果:
-34
-1
-1
-1

 

運算過程中|操作后使用補碼運算同樣會不斷的將0變成1;最后就會變成111111111111111111...=-1
 
實踐發現如果傳入負數最后n最大會變成-1,而上述算法中(n < 0) ? 1會返回1,不會有異常.

 
6: 總結:這個算法主要是對位運算的運用.這里我總結一下位運算的運用
 |按位或運算: 可以將指定的低位從0變成1,如a|0111 (2進制),這樣就可以將低3位 置為1.
 ^異或運算:這個運算是相同的位得0,不同的得1. 它可以用來反轉低位得值.如
1001^0111(2進制) =1110,后三位反轉了.還有之前學過的可以用來交換a,b: a=a^b;b=b^a;a=a^b;
&按位與操作:可以用來保留后n位:如:010101&0111=000101這樣保留后三位不變,其余為0.
<<左移:左移n等同於乘以2的n次方
>>右移:右移n等同於除以2的n次方,正數右移高位補0,負數右移高位補1
>>>無符號右移:無論是正數還是負數,高位都補0。
(左移右移時需要注意范圍)
 
應用:
//判斷兩個int類型數是否同正負:
//只要看高位的數是不是不同即可
public static boolean SameSymbolInt(int a,int b){
    return ((a >> 31) ^ (b >> 31)) == 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM