在看JDK1.7中ArrayDeque源碼時,有一個函數是這樣寫的:
private void allocateElements(int numElements) {
int initialCapacity = MIN_INITIAL_CAPACITY;
// Find the best power of two to hold elements.
// Tests "<=" because arrays aren't kept full.
if (numElements >= initialCapacity) {
initialCapacity = numElements;
initialCapacity |= (initialCapacity >>> 1);
initialCapacity |= (initialCapacity >>> 2);
initialCapacity |= (initialCapacity >>> 4);
initialCapacity |= (initialCapacity >>> 8);
initialCapacity |= (initialCapacity >>> 16);
initialCapacity++;
if (initialCapacity < 0) // Too many elements, must back off
initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
}
elements = (E[]) new Object[initialCapacity];
}
其中的if區域是爲了找到大於numElements的最小2的次冪數,它是用移位、位或操作完成的。
initialCapacity |= (initialCapacity >>> 1);
initialCapacity |= (initialCapacity >>> 2);
initialCapacity |= (initialCapacity >>> 4);
initialCapacity |= (initialCapacity >>> 8);
initialCapacity |= (initialCapacity >>> 16);
上面這段代碼的效果是將initialCapacity 的最高位1的所有低位全部變爲1。如下圖所示:
解釋下第一個位操作:
initialCapacity |= (initialCapacity >>> 1);
先將initialCapacity 邏輯右移一位(高位補0),再與initialCapacity 做位或,這樣就將initialCapacity最高位1的下一位也變爲了1,如下:
接下來的第二句位操作
initialCapacity |= (initialCapacity >>> 2);
會將initialCapacity最高位1的下面3位都變爲了1。
由於在java中整型是固定的32位,所以這5次位操作後,initialCapacity最高位1的所有低位全部也變爲1。然後再執行
initialCapacity++;
就會得到大於initialCapacity的最小2的次冪數。
有一個特殊情況需要處理,即initialCapacity的最高位1是在第31位上:
01XXXXXX XXXXXXXX XXXXXXXX XXXXXXXX,這樣在進行所有操作後initialCapacity會變爲:
10000000 00000000 00000000 00000000,最高位爲1,實際上就上溢爲一個負數。爲了處理這種情況,會將initialCapacity右移一位,這樣它就變爲了一個很大的整數(2的30次冪)。