public E pollFirst() {
int h = head;
@SuppressWarnings("unchecked")
E result = (E) elements[h];
// Element is null if deque empty
if (result == null)
return null;
elements[h] = null; // Must null out slot
head = (h + 1) & (elements.length - 1);
return result;
}
public E pollLast() {
int t = (tail - 1) & (elements.length - 1);
@SuppressWarnings("unchecked")
E result = (E) elements[t];
if (result == null)
return null;
elements[t] = null;
tail = t;
return result;
}
以下2行是什么意思? 这是一个按位操作吗?为什么他们使用它以及这里的目的是什么?
head = (h + 1) & (elements.length - 1);
int t = (tail - 1) & (elements.length - 1);
我知道使用按位的一个方案是在1个变量中打包2个值。但似乎事实并非如此。
答案 0 :(得分:6)
看看初始化代码 - Deque表示为一个大小始终为2的幂的数组:
195 public ArrayDeque(int numElements) {
196 allocateElements(numElements);
197 }
124 private void allocateElements(int numElements) {
125 int initialCapacity = MIN_INITIAL_CAPACITY;
126 // Find the best power of two to hold elements.
127 // Tests "<=" because arrays aren't kept full.
128 if (numElements >= initialCapacity) {
129 initialCapacity = numElements;
130 initialCapacity |= (initialCapacity >>> 1);
131 initialCapacity |= (initialCapacity >>> 2);
132 initialCapacity |= (initialCapacity >>> 4);
133 initialCapacity |= (initialCapacity >>> 8);
134 initialCapacity |= (initialCapacity >>> 16);
135 initialCapacity++;
136
137 if (initialCapacity < 0) // Too many elements, must back off
138 initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
139 }
140 elements = (E[]) new Object[initialCapacity];
141 }
所以elements.length - 1
是二进制基本上是在超出数组大小之前的一系列1
位。
例如,如果elements
初始化为大小为16的数组,则elements.length - 1
为15,表示0..001111
(截断的前导零)。
因此,当head
方法中重置pollFirst
元素(由1提前)时,将使用按位&
运算符以使Deque循环。同样,如果elements
的大小为16且当前head
为15,那么head + 1
将为16,因此:
10000
01111
-----
00000
意思是,head
被重置为索引0.这允许您重用已经分配的空间,使用数组及其插入和检索的O(1)效率,而无需分配新的空间。
对于重置pollLast
变量的tail
也是如此,即如果tail
为0且elements
的大小为16,则:
tail 00000
tail-1 11111 (-1 in two's complement)
01111
-----
01111
含义tail
递减一个值,但从0移到elements.length - 1
。
你可以用更复杂的&#34;来实现同样的目标。 if语句(或使用三元运算符),但这是实现循环数组的一种相当常见且可接受的方式。
答案 1 :(得分:0)
这是一种更有效的计算(head+1) % elements.length
的方法,我们可以这样做,因为elements.length
是2的幂。它更有效,因为 mod 运算符比较昂贵到按位和。
另一方面,仅使用tail
的 mod 不起作用,因为在Java中-1 % N == -1
。