问题引入
/* Used to shift left or right for a partial word mask */
private static final long WORD_MASK = 0xffffffffffffffffL;
/**
* Sets the bits from the specified {@code fromIndex} (inclusive) to the
* specified {@code toIndex} (exclusive) to {@code true}.
*
* @param fromIndex index of the first bit to be set
* @param toIndex index after the last bit to be set
* @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
* or {@code toIndex} is negative, or {@code fromIndex} is
* larger than {@code toIndex}
* @since 1.4
*/
public void set(int fromIndex, int toIndex) {
checkRange(fromIndex, toIndex);
if (fromIndex == toIndex)
return;
// Increase capacity if necessary
int startWordIndex = wordIndex(fromIndex);
int endWordIndex = wordIndex(toIndex - 1);
expandTo(endWordIndex);
long firstWordMask = WORD_MASK << fromIndex;
long lastWordMask = WORD_MASK >>> -toIndex;
if (startWordIndex == endWordIndex) {
// Case 1: One word
words[startWordIndex] |= (firstWordMask & lastWordMask);
} else {
// Case 2: Multiple words
// Handle first word
words[startWordIndex] |= firstWordMask;
// Handle intermediate words, if any
for (int i = startWordIndex+1; i < endWordIndex; i++)
words[i] = WORD_MASK;
// Handle last word (restores invariants)
words[endWordIndex] |= lastWordMask;
}
checkInvariants();
}
这个函数的作用是把起、始比特位之间的比特全部置为true(二进制1b),其余位不变。其中第27行是
long lastWordMask = WORD_MASK >>> -toIndex;
以参数是30–150位为例,那么lastWord是128–192位对应的word,lastWordMask是128–150位为1b、151–192位为0b的mask。
在看这段代码之前,我理解的实现方式是
int rightShift = 64 - (toIndex % 64)
long lastWordMask = WORD_MASK >>> rightShift;
rightShift表示要右移的位数。那么两种方式是如何等价的呢?
原来如此
后来去查了一下资料,移位运算符:>>(有符号右移)、<<(有符号左移)和 >>>(无符号右移)所移动的位数,为右操作数二进制表示的后5个(左操作数是int型)或后6个(左操作数是long型)比特位对应的整数。
以 WORD_MASK >>> -1为例,因为WORD_MASK为long型,所以取-1二进制表示(计算机中负数二进制为补码)的后6位(0b111111)对应的整数63,这与64 - (1 % 64)的结果相同,但由于前者是比特位运算,所以速度更快。
附上Java原始文档对移位运算符讲解的链接–Shift Operators.