当我找到这个实现时,我正在查看ArrayDeque.contains(Object o)
的源代码:
/**
* Returns {@code true} if this deque contains the specified element.
* More formally, returns {@code true} if and only if this deque contains
* at least one element {@code e} such that {@code o.equals(e)}.
*
* @param o object to be checked for containment in this deque
* @return {@code true} if this deque contains the specified element
*/
public boolean contains(Object o) {
if (o == null)
return false;
int mask = elements.length - 1;
int i = head;
Object x;
while ( (x = elements[i]) != null) {
if (o.equals(x))
return true;
i = (i + 1) & mask;
}
return false;
}
这里,数组大小是2的指数,因此mask
应该是一个全1的二进制数。在我看来,i = (i + 1) & mask
与i = i + 1
完全相同。谁能告诉我为什么这样实施呢?
答案 0 :(得分:2)
我不熟悉实现,但这看起来像一个“循环数组”。 head
是第一个元素的索引,通过递增和屏蔽边界周围的迭代循环。
数组中的“last”插槽始终为空(== null
),如果找不到该对象,将结束迭代,并返回false
。
答案 1 :(得分:2)
这是为了包装一个计数器。正如您已经说过的,如果元素的数量是2的幂,那么AuthProvider
将是所有位1。
elements.length -1
现在我们再次增加
mask = 7 // we assume a elements.length of 8
x = (x + 1) & mask // will be 7 and 7, so result is 7
实现相同结果的其他可能更具可读性的方法是:
x = (x + 1) & mask // now it is 8 and 7, so result will be zero
但屏蔽它只是速度(不是可读性)的改进。
答案 2 :(得分:1)
此行应用模数限制增量操作的快速版本。
i = (i + 1) & (length - 1);
长度为8,你得
0 -> 1
1 -> 2
2 -> 3
3 -> 4
4 -> 5
5 -> 6
6 -> 7
7 -> 0
你知道时钟的类似行为(差不多,因为我们通常以1而不是0开始时钟),
有一个约束,长度必须能写成2 ^ n,2,4,8,16,32,64,128,256,512,1024,....
这是有效的,因为(2 ^ n)-1的位表示是具有n个的掩码。 例如(2 ^ 5)-1是二进制0b00011111。
任何数字0< = x< 2 ^ n将通过掩码(2 ^ n)-1而不进行更改。当应用蒙版时,数字2 ^ n将被设置为0.
更一般的方法是使用modulo%。但是modulo通常比比特操作慢得多,例如"和" (&)