JDK1.8源码(二)——java.util.LinkedList
LinkedList定义
LinkedList 是链表实现的线性表(双链表),元素有序且可以重复。
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
蓝色实线箭头是指Class继承关系
绿色实线箭头是指interface继承关系
绿色虚线箭头是指接口实现关系
由上可知LinkedList继承AbstractSequentialList并且实现了List和Deque,Cloneable, Serializable接口。
①、实现 List 接口
List 接口定义了实现该接口的类都必须要实现的一组方法,如下所示,下面我们会对这一系列方法的实现做详细介绍。
字段属性
//链表元素(节点)的个数 transient int size = 0; //第一个元素的指针 transient Node<E> first; //最后一个元素的指针 transient Node<E> last;
注意这里出现了一个 Node 类,这是 LinkedList 类中的一个内部类,集合里每一个元素就代表一个 Node 类对象,LinkedList 集合就是由许多个 Node 对象类似于手拉着手构成,由此可知,LinkedList是一个双向链表。
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; } }
如图所示:每个节点都prev都保存上一个节点的引用,next保存下一个节点的引用;
需要注意:第一个节点prev没有指向的节点,为null,最后一个节点next也没有指向的节点,也为null
构造函数
①、无参构造函数
public LinkedList() { }
注意:这里不需要初始化链表的大小,不像ArrayList,需要初始化数组的大小才能添加元素
②、泛型参数有参构造函数
public LinkedList(Collection<? extends E> c) { this(); addAll(c); }
将已有元素的集合Collection 的实例添加到 LinkedList 中,下面详细介绍
添加元素
①、add(E e)
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);//新添加一个元素,需要新增一个节点,元素内容为e,prev为当前last节点的地址引用,next为null last = newNode;//将链表尾部指向新节点 if (l == null) first = newNode;//如果链表为空,将这个新节点也设为头部节点,那么新增节点既是头节点也是尾节点,并且头节点的prev和next都是null else l.next = newNode;//链表不为空,将之前存储的原链表尾部节点的next指向新增节点 size++;//节点数加1 modCount++;//和ArrayList中一样,防止集合遍历时做元素的添加 }
此时需要注意,如果链表为空时,第一个元素的指针和最后一个元素的指针都指向当前节点
②、addFirst(E e)
public void addFirst(E e) { linkFirst(e); } private void linkFirst(E e) { final Node<E> f = first;//先用变量 f 存储链表头部节点 final Node<E> newNode = new Node<>(null, e, f);//将指定元素构造成一个新节点,元素内容为e,prev为null,next为当前first节点的地址引用, first = newNode;//将链表头部指向新节点 if (f == null) last = newNode;//如果链表为空,将这个新节点也设为尾节点,那么新增节点既是头节点也是尾节点 else f.prev = newNode;//如果链表不为空,讲原链表的头部节点 f 的上一个节点指向新节点 size++;//节点数加1 modCount++;//和ArrayList中一样,防止集合遍历时做元素的添加 }
③、addLast(E e)
public void addLast(E e) { linkLast(e); }