问题引入
private static final long WORD_MASK
= 0xffffffffffffffffL
;
public void set(int fromIndex
, int toIndex
) {
checkRange(fromIndex
, toIndex
);
if (fromIndex
== toIndex
)
return;
int startWordIndex
= wordIndex(fromIndex
);
int endWordIndex
= wordIndex(toIndex
- 1);
expandTo(endWordIndex
);
long firstWordMask
= WORD_MASK
<< fromIndex
;
long lastWordMask
= WORD_MASK
>>> -toIndex
;
if (startWordIndex
== endWordIndex
) {
words
[startWordIndex
] |= (firstWordMask
& lastWordMask
);
} else {
words
[startWordIndex
] |= firstWordMask
;
for (int i
= startWordIndex
+1; i
< endWordIndex
; i
++)
words
[i
] = WORD_MASK
;
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.