LinkedList源码分析

LinkList源码分析

概况

LinkedList与ArrayList一样实现了List接口,只是ArrayList是List接口的大小可变数组的实现,LinkedList是List接口链表的实现。基于链表实现的方式使得LinkedList在插入和删除时更优于ArrayList,而随机访问则不及ArrayList。

签名

1
2
3
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable

· LinkedList 是一个继承于AbstractSequentialList的双向循环链表,且头结点中不存放数据。它也可以被当作堆栈、队列或双端队列进行操作。
· LinkedList 实现 List 接口,能对它进行队列操作。
· LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。
· LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
· LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
· LinkedList 是非同步的。

变量

1
2
3
transient Node<E> first;
transient Node<E> last;
transient int size = 0;

· first和last分别指向头节点和尾节点。
· size为LinkedList中元素个数。

构造器

1
2
public LinkedList() {
}
1
2
3
4
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}

包含“集合”的构造函数:创建一个包含“集合”的LinkedList

方法

1
2
3
4
5
6
7
8
9
10
11
12
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++;
}

· 在非空节点前插入一个元素


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}

· 删除list的头节点,并返回头节点的值,unlinkLast与之类似,返回尾节点的值


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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;
}

· 将x节点删除,返回被删除节点的值


1
2
3
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index);
Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0)
return false;
Node<E> pred, succ;
if (index == size) {
succ = null;
pred = last;
} else {
succ = node(index);
pred = succ.prev;
}
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null)
first = newNode;
else
pred.next = newNode;
pred = newNode;
}
if (succ == null) {
last = pred;
} else {
pred.next = succ;
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}

· 插入某个容器类


1
2
3
4
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}

· 取list的第一个元素
· 那么,peek()和getFirst()有什么区别?
同样都是返回表中的第一个元素,当为空表时,peek返回一个null,而getFirst会抛出一个NoSuchElementException异常


LinkedList有一个内部类:ListItr。在LinkedList中提供了获取ListItr对象的方法:listIterator(int index)。

1
2
3
4
public ListIterator<E> listIterator(int index) {
checkPositionIndex(index);
return new ListItr(index);
}

ListItr实现了ListIterator接口,可知它是一个迭代器,通过它可以遍历修改LinkedList。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
private class ListItr implements ListIterator<E> {
private Node<E> lastReturned;
private Node<E> next;
private int nextIndex;
private int expectedModCount = modCount;
ListItr(int index) {
// assert isPositionIndex(index);
next = (index == size) ? null : node(index);
nextIndex = index;
}
public boolean hasNext() {
return nextIndex < size;
}
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.item;
}
public boolean hasPrevious() {
return nextIndex > 0;
}
public E previous() {
checkForComodification();
if (!hasPrevious())
throw new NoSuchElementException();
lastReturned = next = (next == null) ? last : next.prev;
nextIndex--;
return lastReturned.item;
}
public int nextIndex() {
return nextIndex;
}
public int previousIndex() {
return nextIndex - 1;
}
public void remove() {
checkForComodification();
if (lastReturned == null)
throw new IllegalStateException();
Node<E> lastNext = lastReturned.next;
unlink(lastReturned);
if (next == lastReturned)
next = lastNext;
else
nextIndex--;
lastReturned = null;
expectedModCount++;
}
public void set(E e) {
if (lastReturned == null)
throw new IllegalStateException();
checkForComodification();
lastReturned.item = e;
}
public void add(E e) {
checkForComodification();
lastReturned = null;
if (next == null)
linkLast(e);
else
linkBefore(e, next);
nextIndex++;
expectedModCount++;
}
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (modCount == expectedModCount && nextIndex < size) {
action.accept(next.item);
lastReturned = next;
next = next.next;
nextIndex++;
}
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}

· lastRetured最近一次返回的节点
· next对下一个元素的引用
· nextIndex下一个节点的index
· expectedModCount修改次数的期望值,初始值为modCount,modCount是AbstractList类中的一个成员变量
· 构造方法接收一个index参数,返回一个ListItr对象,如果index<0或>size,返回null
· checkForComodification();判断expectedModCount和modCount,既修改次数,是否相等,以确保通过ListItr的修改操作正确的反映在LinkedList中,不相等的时候就抛出ConcurrentModificationException异常
· forEachRemaining(Consumer<? super E> action);为每个剩余元素执行给定的操作,直到所有的元素都已经被处理或行动将抛出一个异常


1
private static final long serialVersionUID = 876323262645176354L;

serialVersionUID作用是序列化时保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。