Java集合框架-Collection子接口之一-List接口-LinkedList源码分析
LinkedList类:
- LinkedList:双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素,同事,定义内部类Node,作为LinkedList中保存数据的基本结构。Node除了保存数据,还定义了两个变量:
- prev变量记录前一个元素的位置
- next变量记录下一个元素的位置
- 图:
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
transient int size = 0;
/**
* 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;
...
}
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;
}
}
构造器:
使用LinkedList list = new LinkedList();
public LinkedList() {
}
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
添加元素add(E e)方法的调用:
-
方法的调用链(默认使用的是尾插法):add(E e)->linkLast(E e)
-
调用步骤解析:
- add(E e)方法中调用linkLast(E e);
- 在linkLast(E e)方法中先将容器中的Node last属性赋值为l变量,作为链表末尾节点
- 调用Node(Node prev, E element, Node next)构造方法,将l链表末尾节点作为所要添加的新节点的前置节点。把null作为新节点的后继节点
- 因为是尾插法,所以讲容器last属性赋值为新节点
- 判断新节点的前置节点是否为空
- 如果为空(说明新节点为第一个元素,也是头节点),则将LinkedList容器的first属性赋值为新节点
- 如果不为空则将前一个节点的next属性赋值指向(赋值为)新节点。
- 容器容量计数size++;
- 容器操作次数计数modeCount++;
-
public boolean add(E e) { linkLast(e); return true; } 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++; } 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; } }
总结
-
LinkedList list = new LinkedList(); //内部声明了Node类型的first和last属性,默认值为null
-
list.add(123);//将123封装到Node中,创建了Node对象
-
其中Node定义为:
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;
}
}
- LinkeList为双向链表,LinkedList不需要扩容,增加元素只要增加Node就行了