(接上文《源码阅读(10):Java中主要的Queue、Deque结构——ArrayDeque集合(上)》)
2.4、ArrayDeque中的移除操作
无论你使用任何诸如remove()、removeFirst()、removeLast()的方法从ArrayDeque集合的头部或者尾部移除数据,实际上ArrayDeque集合中实际执行工作的方法只有两个,它们是pollLast()方法和pollFirst()方法——前者是从ArrayDeque集合尾部移除数据,后者是从ArrayDeque集合头部移除数据。所以本小节主要就是对这两个方法进行详细说明,首先给出代码片段:
// 该方法从elements数组的头部,基于head变量记录的索引位置移除数据
public E pollFirst() {
int h = head;
E result = (E) elements[h];
// Element is null if deque empty
if (result == null)
return null;
// 设置成null,以便帮助GC回收
elements[h] = null;
// 这句代码已经在上文进行过详细分析,就不再赘述了
head = (h + 1) & (elements.length - 1);
return result;
}
// 该方法从elements数组的尾部,基于tail变量记录的索引位置移除数据
public E pollLast() {
// 这句代码也已经在上文进行过详细分析
// 由于在操作前tail索引位指向下一次操作的空闲数据位
// 所以这里要首先在elements数组的有效数据范围内循环减一,才能让变量t指向真实的elements数组尾部
int t = (tail - 1) & (elements.length - 1);
E result = (E) elements[t];
if (result == null)
return null;
// 设置成null,以便帮助GC回收
elements[t] = null;
tail = t;
return result;
}
这里我们用图文结合的方式,对以上两个方法的主要执行过程进行说明。
- pollFirst()方法中的主要执行过程:
请注意,实际上“E result = (E) elements[t];”这句代码在内存中发生的情况无法通过上图反应出来,如果读者不清楚JVM中内存堆栈区的工作原理,那么读者只需要知道通过这代码,原来存储在elements[t]数组位置的数据对象会被一个新的变量“result”所引用,以便在方法最后返回这个刚被移出elements数组的数据。
- pollLast()方法的主要执行过程:
实际上上图中展示的pollLast()方法的工作场景属于比较常见的场景,当然还有一些特别的场景,例如pollLast()方法操作前tail记录的索引位置刚好是ele