原理
LinkedList 的底层实现是双向链表,不支持随机访问,因此查询速度相对较慢,但删除和插入元素则会很快,只需更改节点的前驱和后继的指向。
源码分析
//元素个数
transient int size = 0;
//第一个元素
transient Node<E> first;
//最后一个元素
transient Node<E> last;
//空的构造函数
public LinkedList() {
}
//带集合参数的构造函数
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
//将元素设置为第一个节点
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
//如果第一个节点为空,最后一个节点也为空
if (f == null)
last = newNode;
else
f.prev = newNode;
//大小加1
size++;
//fail-fast 机制
modCount++;
}
//将元素设置为最后一个节点
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;
//大小加1
size++;
//fail-fast 机制
modCount++;
}
//将元素置为某一节点的前面
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
//解除 first 节点
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
//确定 f 为 first 节点,且不为空
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
//将 first 指向 next
first = next;
//如果下一个节点为空,则将 last 置为空
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
//解除最后一个节点
private E unlinkLast(Node<E> l) {
// assert l == last && l != null;
//确定 l 为 last 节点,且不为空
final E element = l.item;
final Node<E> prev = l.prev;
l.item = null;
l.prev = null; // help GC
将 last 的前驱置为 last
last = prev;
如果前驱为空,则置 first 为空
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
}
//解除指定元素
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;
}