一、概述
LinkedList是一种线性表,它是一种抽象数据类型(ADT),基于双向链(doubly linked list)表实现。
二、继承关系图
注意:其中红色线为内部类(inner class)。
三、双向链表
双链表:每一个节点的头部指向上个节点,尾部指向下一个节点,中间储存着当前data。通过如图的方式连接起来。
第一个元素的prev节点为null,最后一个元素的next节点为null。
添加操作:新建new node,将last节点的next设置为新节点,这样新节点成为last。
删除操作:将被删除节点的上一个节点的next设置为被删除元素的next,将被删除节点的下一个元素的prev设置为被删除节点的prev。
节点的代码实现(摘自JDK1.8版本):
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
Node类是LinkedList的一个内部类(inner class)。这个类实现了双链表的节点。item指向当前元素,next指向下一个节点,prev指向上一个节点,通过一个全参构造函数可以新建一个链表节点。因为这种特殊的构造,所以LinkedList只需要储存第一个节点和最后一个节点即可以将全部节点链接起来。JDK源码中的first字段和last字段就是双链表的头和尾。这两个字段被transient修饰,无法被序列化(在后续会讲到LinkedList序列化的问题)。
/**<p>摘自JDK1.8</p>
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node<E> first;
/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
transient Node<E> last;
插入操作的实现代码实现:将被添加的元素添加到链表尾部。原理即为上面讲到的插入操作。元素也可以插入。
/**<p>摘自JDK1.8</p>
* Links e as last element.
*/
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++; //该字段的作用会在后面章节讲到
}
删除操作的代码实现:
/**<p>摘自JDK1.8</p>
* Removes the first occurrence of the specified element from this list,
* if it is present. If this list does not contain the element, it is
* unchanged. More formally, removes the element with the lowest index
* {@code i} such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
* (if such an element exists). Returns {@code true} if this list
* contained the specified element (or equivalently, if this list
* changed as a result of the call).
*
* @param o element to be removed from this list, if present
* @return {@code true} if this list contained the specified element
*/
public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x); //将节点移除的方法
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
unlink(Node<E> x)方法:
/**
* Unlinks non-null node x.
*/
E unlink(Node<E> x) {
// assert x != null;
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.prev;
if (prev == null) {
first = next;
} else {
prev.next = next;
x.prev = null;
}
if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
}
x.item = null;
size--;
modCount++;
return element;
}