java.util.LinkedList
- 双向链表实现的List。
- 基于JDK 1.8。
- 没有使用标准的注释,并适当调整了代码的缩进以方便介绍。
- 里面很多方法的实现是一样的,不过可以让外界感觉其提供了更多的行为。
- 需要花比ArrayList更多一点的时间理解
package com.anxpp.thinkinjava.chapter11.sourse; import java.util.AbstractSequentialList; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.Deque; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; /** * LinkedList底层使用双向链表,实现了List和deque。实现所有的可选List操作,并可以只有所有元素(包括空值) * 其大小理论上仅受内存大小的限制 * * 所有的操作都可以作为一个双联列表来执行(及对双向链表操作)。 * 把对链表的操作封装起来,并对外提供看起来是对普通列表操作的方法。 * 遍历从起点、终点、或指定位置开始 * 内部方法,注释会描述为节点的操作(如删除第一个节点),公开的方法会描述为元素的操作(如删除第一个元素) * * LinkedList不是线程安全的,如果在多线程中使用(修改),需要在外部作同步处理。 * * 需要弄清元素(节点)的索引和位置的区别,不然有几个地方不好理解,具体在碰到的地方会解释。 * * 迭代器可以快速报错 */ public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable { //容量 transient int size = 0; //首节点 transient Node<E> first; //尾节点 transient Node<E> last; //默认构造函数 public LinkedList() { } //通过一个集合初始化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; //如果之前首节点为空(size==0),那么尾节点就是首节点 else f.prev = newNode; //如果之前首节点不为空,之前的首节点的前一个节点为当前首节点 size++; //长度+1 modCount++; //修改次数+1 } //使用对应参数作为尾节点 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; //如果之前尾节点为空(size==0),首节点即尾节点 else l.next = newNode; //如果之前尾节点不为空,之前的尾节点的后一个就是当前的尾节点 size++; modCount++; } //在指定节点前插入节点,节点succ不能为空 void linkBefore(E e, Node<E> succ) { final Node<E> pred = succ.prev;//获取前一个节点 final Node<E> newNode = new Node<>(pred, e, succ);//使用参数创建新的节点,向前指向前一个节点,向后指向当前节点 succ.prev = newNode;//当前节点指向新的节点 if (pred == null) first = newNode;//如果前一个节点为null,新的节点就是首节点 else pred.next = newNode;//如果存在前节点,那么前节点的向后指向新节点 size++; modCount++; } //删除首节点并返回删除前首节点的值,内部使用 private E unlinkFirst(Node<E> f) { final E element = f.item;//获取首节点的值 final Node<E> next = f.next;//得到下一个节点 f.item = null; f.next = null; //便于垃圾回收期清理 first = next; //首节点的下一个节点成为新的首节点 if (next == null) last = null; //如果不存在下一个节点,则首尾都为null(空表) else next.prev = null;//如果存在下一个节点,那它向前指向null size--; modCount++; return element; } //删除尾节点并返回删除前尾节点的值,内部使用 private E unlinkLast(Node<E> l) { final E element = l.item;//获取值 final Node<E> prev = l.prev;//获取尾节点前一个节点 l.item = null; l.prev = null; //便于垃圾回收期清理 last = prev; //前一个节点成为新的尾节点 if (prev == null) first = null; //如果前一个节点不存在,则首尾都为null(空表) else prev.next = null;//如果前一个节点存在,先后指向null size--; modCount++; return element; } //删除指定节点并返回被删除的元素值 E unlink(Node<E> x) { //获取当前值和前后节点 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; //方便gc回收 } if (next == null) { last = prev; //如果后一个节点为空(如当前节点为尾节点),当前节点前一个成为新的尾节点 } else { next.prev = prev;//如果后一个节点不为空,后一个节点向前指向当前的前一个节点 x.next = null; //方便gc回收 } x.item = null; //方便gc回收 size--; modCount++; return element; } //获取第一个元素 public E getFirst() { final Node<E> f = first;//得到首节点 if (f == null) //如果为空,抛出异常 throw new NoSuchElementException(); return f.item; } //获取最后一个元素 public E getLast() { final Node<E> l = last;//得到尾节点 if (l == null) //如果为空,抛出异常 throw new NoSuchElementException(); return l.item; } //删除第一个元素并返回删除的元素 public E removeFirst() { final Node<E> f = first;//得到第一个节点 if (f ==