(接上文《源码阅读(6):Java中主要的List、Deque结构——LinkedList集合(上)》)
1.3. LinkedList集合的移除操作
LinkedList集合的移除操作和LinkedList集合的添加操作同样具有阅读意义。实际上在LinkedList集合中有三个关键方法负责移除集合中的元素,它们是unlinkFirst(Node f) 方法、unlinkLast(Node l) 方法和unlink(Node x) 方法。无论是LinkedList集合中的removeFirst()方法、removeLast()方法还是remove(Object o)方法,其方法实现都基于前者提到的三个方法。本节我们将详细介绍这三个方法:
1.3.1、unlinkFirst(Node f) 方法
unlinkFirst(Node f) 方法用于移除LinkedList集合双向链表结构的“头”节点,并重新定义后续节点为新的“头”节点。注意该方法的入参“f”,就是当前双向链表的“头”节点——这个入参“f”在经过调用者处理后一定不会为null。
/**
* Unlinks non-null first node f.
*/
private E unlinkFirst(Node<E> f) {
// 定义一个element变量,该变量记录当前“头”节点的数据信息,因为最后要进行返回
final E element = f.item;
// 定义一个next变量,该变量记录当前“头”节点的后续节点,注意这里的值可能为null
final Node<E> next = f.next;
// 设定当前“头”节点的数据引用、后置节点引用为null
f.item = null;
f.next = null; // help GC
// 设定双向链表的新的“头”节点为当前节点的后续节点
first = next;
// 如果条件成立,说明在完成“头”节点的移除操作后,双向链表中已没有任何节点了
// 那么需要同时设定双向链表中的“last”变量为null
if (next == null)
last = null;
// 其它情况下设置新的“头”节点的前置引用为null——因为原来的前置引用指向操作前的“头”节点
else
next.prev = null;
// 链表大小 - 1
size--;
// LinkedList集合的操作次数 + 1
modCount++;
return element;
}
这里我们还是通过图文说明的方式将以上代码过程再进行一次说明,如下图所示:
1.3.2、unlinkLast(Node l) 方法
unlinkLast(Node l) 方法用于移除LinkedList集合双向链表结构的“尾”节点,并重新定义前置节点为新的“尾”节点。注意该方法的入参“l”,就是当前双向链表的“尾”节点引用——这个入参“l”在经过调用者处理后一定不会为null。
/**
* Unlinks non-null last node l.
*/
private E unlinkLast(Node<E> l) {
// 定义一个新的变量“element”,该变量用于记录当前双向链表“尾”节点的数据,以便方法最后进行返回
final E element = l.item;
// 定义一个新的变量“prev”,该变量将指向当前“尾”节点的前置节点。注意,这个“prev”变量可能为null
final Node<E> prev = l.prev;
// 设定当前“尾”节点的数据引用为null、前置引用也为null
l.item = null;
l.prev = null; // help GC
// 设定当前“尾”节点的前置节点为新的“尾”节点
last = prev;