Java集合之LinkedList源码解析
下面我们来看看LinkedList的底层实现,
它继承抽象方法AbstractSequentialList<E>,实现List<E>, Deque<E>, Cloneable, java.io.Serializable接口
它的成员属性有,
1 transient int size = 0; 2 transient Node<E> first; 3 transient Node<E> last;
size表示该集合的元素个数,初始值为0,first指向第一个Node,last指向最后一个Node,
Node<E>是一个静态内部类,
1 private static class Node<E> {
2 E item;
3 Node<E> next;
4 Node<E> prev;
5
6 Node(Node<E> prev, E element, Node<E> next) {
7 this.item = element;
8 this.next = next;
9 this.prev = prev;
10 }
11 }
item指当前元素,next是下一个元素的引用,prev是前一个元素的引用,
LinkedList是一个双向链表,
百科中对于链表的定义是
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。
所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
新增元素
假如我们有如下的代码,
1 public static void main(String[] args) {
2 LinkedList list = new LinkedList<String>();
3 list.add("ABC");
4 }
我们进到add(E e),
1 public boolean add(E e) {
2 linkLast(e);
3 return true;
4 }
第2行,进到linkLast(E e),
1 void linkLast(E e) {
2 final Node<E> l = last;
3 final Node<E> newNode = new Node<>(l, e, null);
4 last = newNode;
5 if (l == null)
6 first = newNode;
7 else
8 l.next = newNode;
9 size++;
10 modCount++;
11 }
第2行,将队列的尾节点赋值给 l
第3行,构建一个Node,
第4行,新构建的Node追加到队尾,
第5-8行,判断原始为节点是否为空,如果为空,当前Node是首次新增,
第9行,size自增,
查找元素
假如我们有如下一段代码
1 public static void main(String[] args) {
2 LinkedList list = new LinkedList<String>();
3 list.add("ABC");
4 list.add("DEF");
5
6 list.get(0);
7 }
进到get(int index)方法,
1 public E get(int index) {
2 checkElementIndex(index);
3 return node(index).item;
4 }
第2行,检验index是否是在链表内
第3行,根据index得到node,该node的item就是要的值,下面进到node(int index)
1 Node<E> node(int index) {
2 // assert isElementIndex(index);
3
4 if (index < (size >> 1)) {
5 Node<E> x = first;
6 for (int i = 0; i < index; i++)
7 x = x.next;
8 return x;
9 } else {
10 Node<E> x = last;
11 for (int i = size - 1; i > index; i--)
12 x = x.prev;
13 return x;
14 }
15 }
第4~14行,说的如果index比 size/2 小,则从前往后搜索,否则,从后往前搜索
插入元素
假如我们我如下这段代码,
1 public static void main(String[] args) {
2 LinkedList<String> list = new LinkedList<String>();
3 list.add("ABC");
4 list.add("DEF");
5
6 list.add(1, "XYZ");
7 System.out.print(list); //[ABC, XYZ, DEF]
8 }
在index个元素后面,插入element,我们进到add(int index, E element),
1 public void add(int index, E element) {
2 checkPositionIndex(index);
3
4 if (index == size)
5 linkLast(element);
6 else
7 linkBefore(element, node(index));
8 }
第2行,index校验,必须大于等于0,且小于等于size,
第4~7行,如果是在size个元素后插入,直接在链表尾部追加,和上面的新增方式一样,
否则,先检索到index的元素,把待插入的元素放在node(index)之前即可,
删除元素
删除元素有两种,第一按照索引删除(从0开始),第二种是根据值来删除,因为LinkedList中元素可重复,在源码中从头开始遍历直到找到一个为止,
两种方式分两步
1.找到对应的Node<E>,
2.调用unlink(Node<E> x)
下面来看一下unlink(Node<E> x),
1 E unlink(Node<E> x) {
2 // assert x != null;
3 final E element = x.item;
4 final Node<E> next = x.next;
5 final Node<E> prev = x.prev;
6
7 if (prev == null) {
8 first = next;
9 } else {
10 prev.next = next;
11 x.prev = null;
12 }
13
14 if (next == null) {
15 last = prev;
16 } else {
17 next.prev = prev;
18 x.next = null;
19 }
20
21 x.item = null;
22 size--;
23 modCount++;
24 return element;
25 }
这里我就不再逐行解释了,比较简单。

浙公网安备 33010602011771号