/**
* List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。
* 除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。
* 这些操作允许将链接列表用作堆栈、队列或双端队列。
* 此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。
* 所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。
* 注意,此实现不是同步的。如果多个线程同时访问一个链接列表,而其中至少一个线程从结构上修改了该列表,则它必须 保持外部同步。
* (结构修改指添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改。)
* 这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,
* 则应该使用 Collections.synchronizedList 方法来“包装”该列表。
* 最好在创建时完成这一操作,以防止对列表进行意外的不同步访问,如下所示:
* List list = Collections.synchronizedList(new LinkedList(...));
* 此类的 iterator 和 listIterator 方法返回的迭代器是快速失败 的:在迭代器创建之后,如果从结构上对列表进行修改,
* 除非通过迭代器自身的 remove 或 add 方法,其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException。
* 因此,面对并发的修改,迭代器很快就会完全失败,而不冒将来不确定的时间任意发生不确定行为的风险。
* 注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何硬性保证。
* 快速失败迭代器尽最大努力抛出 ConcurrentModificationException。
* 因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测程序错误。
* @param <E> 在此 collection 中保持的元素的类型
*/
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
/*
* 继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
* 实现 List 接口,能对它进行队列操作。
* 实现 Deque 接口,即能将LinkedList当作双端队列使用。
* 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
* 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
*/
/*
* 实现Serilizable接口时,将不需要序列化的属性前添加关键字transient,
* 序列化对象的时候,这个属性就不会序列化到指定的目的地中。
*/
// 此列表的元素数
transient int size = 0;
/*
* 指向第一个节点的指针。
* 不变式: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node<E> first;
/*
* 指向最后一个节点的指针。
* 不变式: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
transient Node<E> last;
/**
* 构造一个空列表
*/
public LinkedList() {
}
/**
* 构造一个包含指定 collection 中的元素的列表,
* 这些元素按其 collection 的迭代器返回的顺序排列。
* @param c 要将其元素放入此列表的 collection
*/
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);//添加c 中的所有元素到此列表的结尾,顺序是c 的迭代器返回这些元素的顺序。
}
/**
* 将e作为第一个节点元素。
* @param e 要添加的元素
*/
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;
else
f.prev = newNode;
size++;
modCount++;
}
/**
* 将e作为最后一个节点元素。
* @param e 要添加的元素
*/
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++;
}
/**
* 在非空节点succ之前插入元素e。
* @param e 要插入的元素
* @param succ 非空节点
*/
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++;
}
/**
* 取消非空第一节点f的链接
* @param f 此列表的第一个节点
* @return 此列表的第一个元素
*/
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;
}
/**
* 取消非空最后一个节点l的链接
* @param l 此列表的最后一个节点
* @return 此列表的最后一个元素
*/
private E unlinkLast(Node<E> l) {
// assert l == last && l != null;
final E element = l.item;
final Node<E> prev = l.prev;
l.item = null;
l.prev = null; // help GC
last = prev;
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
}
/**
* 取消非空节点x的连接
* @param x 非空节点
* @return 节点之前相关联的元素
*/
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;
}
/**
* 返回此列表的第一个元素
* 覆写:接口 Deque<E> 中的 getFirst
* @return 此列表的第一个元素
*/
public E getFirst() {
final Node<E> f = first;
if (f == null)// 如果此列表为空
throw new NoSuchElementException();
return f.item;
}
/**
* 返回此列表的最后一个元素。
* 覆写:接口 Deque<E> 中的 getLast
* @return 此列表的最后一个元素
*/
public E getLast() {
final Node<E> l = last;
if (l == null)// 如果此列表为空
throw new NoSuchElementException();
return l.item;
}
/**
* 移除并返回此列表的第一个元素。
* 覆写:接口 Deque<E> 中的 removeFirst
* @return 此列表的第一个元素
*/
public E removeFirst() {
final Node<E> f = first;
if (f == null)//如果此列表为空
throw new NoSuchElementException();
return unlinkFirst(f);// 取消非空第一节点f的链接
}
/**
* 移除并返回此列表的最后一个元素。
* 覆写:接口 Deque<E> 中的 removeLast
* @return 此列表的最后一个元素
*/
public E removeLast() {
final Node<E> l = last;
if (l == null)// 如果此列表为空
throw new NoSuchElementException();
return unlinkLast(l);// 取消非空最后一个节点l的链接
}
/**
* 将指定元素插入此列表的开头。
*覆写:接口 Deque<E> 中的 addFirst
* @param e 要添加的元素
*/
public void addFirst(E e) {
linkFirst(e);
}
/**
* 将指定元素添加到此列表的结尾。
* 此方法等效于 add(E)。
* 覆写:接口 Deque<E> 中的 addLast
* @param e 要添加的元素
*/
public void addLast(E e) {
linkLast(e);
}
/**
* 如果此列表包含指定元素,则返回 true。
* 更确切地讲,当且仅当此列表包含至少一个满足 (o==null ? e==null : o.equals(e)) 的元素 e 时返回 true。
* 覆盖:类 AbstractCollection<E> 中的 contains
* @param o 要测试在此列表中是否存在的元素
* @return 如果此列表包含指定元素,则返回 true
*/
public boolean contains(Object o) {
return indexOf(o) != -1;
}
/**
* 返回此列表的元素数
* 覆写:接口 Collection<E> 中的 size
* 覆写:接口 Deque<E> 中的 size
* 覆写:接口 List<E> 中的 size
* 覆写:类 AbstractCollection<E> 中的 size
* @return 此列表的元素数
*/
public int size() {
return size;
}
/**
* 将指定元素添加到此列表的结尾。
* 此方法等效于 addLast(E)。
* 覆盖:类 AbstractList<E> 中的 add
* @param e 要添加到此列表的元素
* @return true(根据 Collection.add(E) 的规定)
*/
public boolean add(E e) {
linkLast(e);
return true;
}
/**
* 从此列表中移除首次出现的指定元素(如果存在)。
* 如果列表不包含该元素,则不作更改。更确切地讲,
* 移除具有满足 (o==null ? get(i)==null : o.equals(get(i))) 的最低索引 i 的元素(如果存在这样的元素)。
* 如果此列表已包含指定元素(或者此列表由于调用而发生更改),则返回 true。
* 覆盖:类 AbstractCollection<E> 中的 remove
* @param o 要从此列表删除的元素,如果存在
* @return 如果此列表包含指定元素,则返回 true
*/
public boolean remove(Object o) {
if (o == null) {// 为空
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {// 当前节点的元素为空,取消关联
unlink(x);
return true;
}
}
} else {// 非空
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {// 当前节点的元素等于o,取消关联
unlink(x);
return true;
}
}
}
return false;
}
/**
* 添加指定 collection 中的所有元素到此列表的结尾,
* 顺序是指定 collection 的迭代器返回这些元素的顺序。
* 如果指定的 collection 在操作过程中被修改,则此操作的行为是不确定的。
* (注意,如果指定 collection 就是此列表并且非空,则此操作的行为是不确定的。)
* 覆盖:类 AbstractCollection<E> 中的 addAll
* @param c 包含要添加到此列表的元素的 collection
* @return 如果此列表由于调用而更改,则返回 true
*/
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
/**
* 将指定 collection 中的所有元素从指定位置开始插入此列表。
* 移动当前在该位置上的元素(如果有),所有后续元素都向右移(增加其索引)。
* 新元素将按由指定 collection 的迭代器返回的顺序在列表中显示。
* 覆盖:类 AbstractSequentialList<E> 中的 addAll
* @param index 在其中插入指定 collection 中第一个元素的索引
* @param c 包含要添加到此列表的元素的 collection
* @return 如果此列表由于调用而更改,则返回 true
*/
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);// 返回指定元素索引处(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;
}
/**
* 从此列表中移除所有元素。
* 覆盖:类 AbstractList<E> 中的 clear
*/
public void clear() {
// 清除节点之间的所有链接是“不必要的”,但是:
// - 如果丢弃的节点驻留在一个以上的代,则帮助生成GC
// - 即使有一个可访问的迭代器,也一定要释放内存
for (Node<E> x = first; x != null; ) {
Node<E> next = x.next;
x.item = null;
x.next = null;
x.prev = null;
x = next;
}
first = last = null;
size = 0;
modCount++;
}
// 位置访问操作
/**
* 返回此列表中指定位置处的元素。
* 覆盖:类 AbstractSequentialList<E> 中的 get
* @param index 要返回的元素的索引
* @return 列表中指定位置的元素
*/
public E get(int index) {
checkElementIndex(index);// 检查索引
return node(index).item;
}
/**
* 将此列表中指定位置的元素替换为指定的元素。
* 覆盖:类 AbstractSequentialList<E> 中的 set
* @param index 要替换的元素的索引
* @param element 要在指定位置存储的元素
* @return 以前在指定位置的元素
*/
public E set(int index, E element) {
checkElementIndex(index);// 检查索引
Node<E> x = node(index); // 返回指定元素索引(index)处的(非空)节点。
E oldVal = x.item;
x.item = element;
return oldVal;
}
/**
* 在此列表中指定的位置插入指定的元素。
* 移动当前在该位置处的元素(如果有),所有后续元素都向右移(在其索引中添加 1)。
* 覆盖:类 AbstractSequentialList<E> 中的 add
* @param index 要在其中插入指定元素的索引
* @param element 要插入的元素
*/
public void add(int index, E element) {
checkPositionIndex(index);// 检查索引
if (index == size)// 等于元素数,将element作为最后一个节点元素。
linkLast(element);
else// 在非空节点node(index)之前插入元素element。
linkBefore(element, node(index));
}
/**
* 移除此列表中指定位置处的元素。
* 将任何后续元素向左移(从索引中减 1)。返回从列表中删除的元素。
* 覆盖:类 AbstractSequentialList<E> 中的 remove
* @param index 要移除的元素的索引
* @return 以前在指定位置的元素
*/
public E remove(int index) {
checkElementIndex(index);// 检查索引
return unlink(node(index)); // 取消非空节点node(index)的连接
}
/**
* 参数是否是现有元素的索引。
* @param index 指定索引
* @return true:是;false:不是
*/
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
}
/**
* 参数是否是迭代器或添加操作的有效位置的索引。
* @param index 指定的索引
* @return true:是;false:不是
*/
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size;
}
/**
* 构造IndexOutOfBoundsException详细信息。
* 在错误处理代码的许多可能重构中,这个“大纲”在服务器和VMs客户端上执行得最好。
* @param index 索引位置
* @return
*/
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}
/**
* 检查指定的元素索引是否是现有元素的索引
* @param index 指定的索引
*/
private void checkElementIndex(int index) {
if (!isElementIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* 检查指定的元素是否是迭代器或添加操作的有效位置的索引
* @param index 指定的索引
*/
private void checkPositionIndex(int index) {
if (!isPositionIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* 返回指定元素索引处的(非空)节点。
* @param index 指定元素索引
* @return
*/
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
// 搜索运算
/**
* 返回此列表中首次出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1。
* 更确切地讲,返回满足 (o==null ? get(i)==null : o.equals(get(i))) 的最低索引 i;
* 如果没有此索引,则返回 -1。
* 覆盖:类 AbstractList<E> 中的 indexOf
* @param o 要搜索的元素
* @return 此列表中第一次出现的指定元素的索引,如果列表不包含该元素,则返回 -1
*/
public int indexOf(Object o) {
int index = 0;
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) // 当前节点的元素为空,返回
return index;
index++;
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) // 当前节点的元素等于o,返回
return index;
index++;
}
}
return -1;
}
/**
* 返回此列表中最后出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1。
* 更确切地讲,返回满足 (o==null ? get(i)==null : o.equals(get(i))) 的最高索引 i;
* 如果没有此索引,则返回 -1。
* 覆盖:类 AbstractList<E> 中的 lastIndexOf
* @param o 要搜索的元素
* @return 此列表中最后出现的指定元素的索引;如果此列表中不包含该元素,则返回 -1
*/
public int lastIndexOf(Object o) {
int index = size;
if (o == null) {
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (x.item == null)// 当前节点的元素为空,返回
return index;
}
} else {
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (o.equals(x.item))// 当前节点的元素等于o,返回
return index;
}
}
return -1;
}
// 队列的操作。
/**
* 获取但不移除此列表的头(第一个元素)。
* 覆写:Queue<E> 中的 peek
* 覆写:Deque<E> 中的 peek
* @return 此列表的头,如果此列表为空,则返回 null
*/
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
/**
* 获取但不移除此列表的头(第一个元素)。
* 覆写:接口 Deque<E> 中的 element
* 覆写:接口 Queue<E> 中的 element
* @return 列表的头
*/
public E element() {
return getFirst();
}
/**
* 获取并移除此列表的头(第一个元素)
* 覆写:Deque<E> 中的 poll
* 覆写:Queue<E> 中的 poll
* @return 此列表的头,如果此列表为空,则返回 null
*/
public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
/**
* 获取并移除此列表的头(第一个元素)。
* 覆写:Deque<E> 中的 remove
* 覆写:Queue<E> 中的 remove
* @return 列表的头
*/
public E remove() {
return removeFirst();
}
/**
* 将指定元素添加到此列表的末尾(最后一个元素)。
* 覆写:Deque<E> 中的 offer
* 覆写:Queue<E> 中的 offer
* @param e 要添加的元素
* @return true(根据 Queue.offer(E) 的规定)
*/
public boolean offer(E e) {
return add(e);
}
// 双端队列的操作
/**
* 在此列表的开头插入指定的元素。
* 覆写: Deque<E> 中的 offerFirst
* @param e 要插入的元素
* @return true(根据 Deque.offerFirst(E) 的规定)
*/
public boolean offerFirst(E e) {
addFirst(e);// 将e插入此列表的开头。
return true;
}
/**
* 在此列表末尾插入指定的元素。
* 覆写:Deque<E> 中的 offerLast
* @param e 要插入的元素
* @return true(根据 Deque.offerLast(E) 的规定)
*/
public boolean offerLast(E e) {
addLast(e); // 将e添加到此列表的结尾。
return true;
}
/**
* 获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
* 覆写:Deque<E> 中的 peekFirst
* @return 此列表的第一个元素;如果此列表为空,则返回 null
*/
public E peekFirst() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
/**
* 获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
* 覆写:Deque<E> 中的 peekLast
* @return 此列表的最后一个元素;如果此列表为空,则返回 null
*/
public E peekLast() {
final Node<E> l = last;
return (l == null) ? null : l.item;
}
/**
* 获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
* 覆写:Deque<E> 中的 pollFirst
* @return E 此列表的第一个元素;如果此列表为空,则返回 null
*/
public E pollFirst() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
/**
* 获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
* 覆写:Deque<E> 中的 pollLast
* @return 此列表的最后一个元素;如果此列表为空,则返回 null
*/
public E pollLast() {
final Node<E> l = last;
return (l == null) ? null : unlinkLast(l);
}
/**
* 将元素推入此列表所表示的堆栈。换句话说,将该元素插入此列表的开头。
* 此方法等效于 addFirst(E)。
* 覆写:Deque<E> 中的 push
* @param e 要推入的元素
*/
public void push(E e) {
addFirst(e);
}
/**
* 从此列表所表示的堆栈处弹出一个元素。换句话说,移除并返回此列表的第一个元素。
* 此方法等效于 removeFirst()。
* 覆写:Deque<E> 中的 pop
* @return 此列表开头的元素(它是此列表所表示的堆栈的顶部)
*/
public E pop() {
return removeFirst();
}
/**
* 从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)。
* 如果列表不包含该元素,则不作更改。
* 覆写:Deque<E> 中的 removeFirstOccurrence
* @param o 要从此列表中移除的元素(如果存在)
* @return 如果该列表已包含指定元素,则返回 true
*/
public boolean removeFirstOccurrence(Object o) {
return remove(o);
}
/**
* 从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)。
* 如果列表不包含该元素,则不作更改。
* 覆写:Deque<E> 中的 removeLastOccurrence
* @param o 要从此列表中移除的元素(如果存在)
* @return 如果该列表已包含指定元素,则返回 true
*/
public boolean removeLastOccurrence(Object o) {
if (o == null) {
for (Node<E> x = last; x != null; x = x.prev) {
if (x.item == null) {//为空,取消链接
unlink(x);
return true;
}
}
} else {
for (Node<E> x = last; x != null; x = x.prev) {
if (o.equals(x.item)) { //一致,取消链接
unlink(x);
return true;
}
}
}
return false;
}
/**
* 返回此列表中的元素的列表迭代器(按适当顺序),从列表中指定位置开始。
* 遵守 List.listIterator(int) 的常规协定。
* 列表迭代器是快速失败 的:在迭代器创建之后,如果从结构上对列表进行修改,
* 除非通过列表迭代器自身的 remove 或 add 方法,其他任何时间任何方式的修改,
* 列表迭代器都将抛出 ConcurrentModificationException。因此,
* 面对并发的修改,迭代器很快就会完全失败,
* 而不冒将来不确定的时间任意发生不确定行为的风险。
* 覆写:List<E> 中的 listIterator
* 覆写:AbstractSequentialList<E> 中的 listIterator
* @param index 要从列表迭代器返回的第一个元素的索引(通过调用 next 方法)
* @return 此列表中的元素的 ListIterator(按适当顺序),从列表中指定位置开始
*/
public ListIterator<E> listIterator(int index) {
checkPositionIndex(index);// 检查索引
return new ListItr(index);
}
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;
}
/**
* 是否有可迭代的下一个元素。
* 覆写: 接口 Iterator<E> 中的 hasNext
*/
public boolean hasNext() {
return nextIndex < size;
}
/**
* 返回列表中的下一个元素。
* @return 列表中的下一个元素。
*/
public E next() {
checkForComodification();// 并发检查
if (!hasNext())// 如果没有可迭代的下一个元素
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.item;
}
/**
* 是否有可迭代的上一个元素。
*/
public boolean hasPrevious() {
return nextIndex > 0;
}
/**
* 返回列表中的前一个元素。
* @return 列表中的上一个元素
*/
public E previous() {
checkForComodification();// 并发检查
if (!hasPrevious())// 如果没有可迭代的上一个元素。
throw new NoSuchElementException();
lastReturned = next = (next == null) ? last : next.prev;
nextIndex--;
return lastReturned.item;
}
/**
* 返回对 next 的后续调用所返回元素的索引。
* (如果列表迭代器在列表的结尾,则返回列表的大小)。
*/
public int nextIndex() {
return nextIndex;
}
/**
* 返回对 previous 的后续调用所返回元素的索引。
* (如果列表迭代器在列表的开始,则返回 -1)。
*/
public int previousIndex() {
return nextIndex - 1;
}
/**
* 从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。
*/
public void remove() {
checkForComodification();// 并发检查
if (lastReturned == null)
throw new IllegalStateException();
Node<E> lastNext = lastReturned.next;
unlink(lastReturned);// 取消非空节点lastReturned的连接
if (next == lastReturned)
next = lastNext;
else
nextIndex--;
lastReturned = null;
expectedModCount++;
}
/**
* 用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。
* @param e 用于替换 next 或 previous 返回的最后一个元素的元素
*/
public void set(E e) {
if (lastReturned == null)
throw new IllegalStateException();
checkForComodification();// 并发检查
lastReturned.item = e;
}
/**
* 将指定的元素插入列表(可选操作)。
* @param e 要插入的元素
*/
public void add(E e) {
checkForComodification();// 并发检查
lastReturned = null;
if (next == null)
linkLast(e); // 将e作为最后一个节点元素。
else
linkBefore(e, next);// 在非空节点next之前插入元素e。
nextIndex++;
expectedModCount++;
}
/**
* 从基础集合中删除此迭代器返回的最后一个元素(可选操作)。
*/
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);// 检查指定的对象引用是否为空
while (modCount == expectedModCount && nextIndex < size) {
action.accept(next.item);// 对next.item执行此操作
lastReturned = next;
next = next.next;
nextIndex++;
}
checkForComodification();// 并发检查
}
/**
* 检查已从结构上修改 此列表的次数是否不一致,用于并发检查
*/
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
/**
* 节点
*/
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;
}
}
/**
* 返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。
* 元素将按从最后一个(尾部)到第一个(头部)的顺序返回。
* @return 以逆向顺序在此双端队列中的元素上进行迭代的迭代器
*/
public Iterator<E> descendingIterator() {
return new DescendingIterator();
}
/**
* 适配器,通过ListItr.previous提供逆向顺序迭代器
*/
private class DescendingIterator implements Iterator<E> {
private final ListItr itr = new ListItr(size());
/**
* 如果仍有元素可以迭代,则返回 true。
*/
public boolean hasNext() {
return itr.hasPrevious(); // 是否有可迭代的上一个元素。
}
/**
* 返回迭代的下一个元素。
*/
public E next() {
return itr.previous();// 返回列表中的前一个元素。
}
/**
* 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
*/
public void remove() {
itr.remove();
}
}
/**
* 浅拷贝LinkedList<E>
* @return
*/
@SuppressWarnings("unchecked")
private LinkedList<E> superClone() {
try {
return (LinkedList<E>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
/**
* 返回此 LinkedList 的浅拷贝。(这些元素本身没有复制。)
* 覆盖:类 Object 中的 clone
* @return 此 LinkedList 实例的浅表副本
*/
public Object clone() {
LinkedList<E> clone = superClone();//浅拷贝LinkedList<E>
// 克隆“原始”状态
clone.first = clone.last = null;
clone.size = 0;
clone.modCount = 0;
//用我们的元素初始化克隆
for (Node<E> x = first; x != null; x = x.next)
clone.add(x.item);// 将指定元素添加到此列表的结尾。
return clone;
}
/**
* 返回以适当顺序(从第一个元素到最后一个元素)包含此列表中所有元素的数组。
* 由于此列表不维护对返回数组的任何引用,因而它将是“安全的”。
* (换句话说,此方法必须分配一个新数组)。因此,调用者可以随意修改返回的数组。
* 此方法充当基于数组的 API 与基于 collection 的 API 之间的桥梁。
* 覆盖:类 AbstractCollection<E> 中的 toArray
* @return 以适当顺序包含此列表中所有元素的数组。
*/
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
return result;
}
/**
* 返回以适当顺序(从第一个元素到最后一个元素)包含此列表中所有元素的数组;
* 返回数组的运行时类型为指定数组的类型。如果指定数组能容纳列表,则在其中返回该列表。
* 否则,分配具有指定数组的运行时类型和此列表大小的新数组。
* 如果指定数组能容纳列表,并有剩余空间(即数组比列表元素多),
* 则紧跟在列表末尾的数组元素会被设置为 null。
* (只有 在调用者知道列表不包含任何 null 元素时,才可使用此方法来确定列表的长度。)
* 像 toArray() 方法一样,此方法充当基于数组的 API 与基于 collection 的 API 之间的桥梁。
* 更进一步说,此方法允许对输出数组的运行时类型上进行精确控制,
* 在某些情况下,可以用来节省分配开销。
* 假定 x 是只包含字符串的一个已知列表。
* 以下代码可用来将该列表转储到一个新分配的 String 数组:
* String[] y = x.toArray(new String[0]);
* 注意,toArray(new Object[0]) 和 toArray() 在功能上是相同的。
* 覆盖:类 AbstractCollection<E> 中的 toArray
* @param a 要在其中存储列表元素的数组(如果它足够大);否则,为其分配具有相同运行时类型的新数组
* @return 包含列表元素的数组
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
a = (T[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);
int i = 0;
Object[] result = a;
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
if (a.length > size)
a[size] = null;
return a;
}
private static final long serialVersionUID = 876323262645176354L;
/**
* 保存此LinkedList实例的状态到流(即序列化它)。
* @serialData 列表的大小(它包含的元素的数量)被发出(int),
* 然后它的所有元素(每个对象)以正确的顺序发出。
* @param s
* @throws java.io.IOException
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// 写出任何隐藏的序列化元素
s.defaultWriteObject();
// 写出大小
s.writeInt(size);
// 按适当的顺序写出所有的元素。
for (Node<E> x = first; x != null; x = x.next)
s.writeObject(x.item);
}
/**
* 从流中重构这个LinkedList实例(即反序列化它)。
* @param s
* @throws java.io.IOException
* @throws ClassNotFoundException
*/
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// 读取任何隐藏的序列化元素
s.defaultReadObject();
// 读出大小
int size = s.readInt();
// 按正确的顺序读取所有元素。
for (int i = 0; i < size; i++)
linkLast((E)s.readObject());
}
/**
* 在此列表中的元素上创建fail-fast的Spliterator。
* Spliterator报告Spliterator.SIZED和Spliterator.ORDERED。
* 覆盖实现应该记录额外特征值的报告。
* 另外Spliterator报告Spliterator.SUBSIZED和实现trySplit允许有限的并行性。
* @return 在此列表中的元素上使用Spliterator
*/
@Override
public Spliterator<E> spliterator() {
return new LLSpliterator<E>(this, -1, 0);
}
/**
* 一个定制的spliterator.iteratorspliterator的变体
*/
static final class LLSpliterator<E> implements Spliterator<E> {
static final int BATCH_UNIT = 1 << 10; // 批处理数组大小增量
static final int MAX_BATCH = 1 << 25; // 最大批量数组大小
final LinkedList<E> list; // null,除非遍历
Node<E> current; // 当前节点;默认空,直到初始化
int est; // 估计大小;默认-1,直到第一次需要
int expectedModCount; // 在est设置时初始化
int batch; // 分批大小
LLSpliterator(LinkedList<E> list, int est, int expectedModCount) {
this.list = list;
this.est = est;
this.expectedModCount = expectedModCount;
}
final int getEst() {
int s; // force initialization
final LinkedList<E> lst;
if ((s = est) < 0) {
if ((lst = list) == null)
s = est = 0;
else {
expectedModCount = lst.modCount;
current = lst.first;
s = est = lst.size;
}
}
return s;
}
/**
* 返回元素个数
*/
public long estimateSize() { return (long) getEst(); }
/**
* 覆盖部分元素的Spliterator,如果不能拆分该Spliterator,则为null
*/
public Spliterator<E> trySplit() {
Node<E> p;
int s = getEst();
if (s > 1 && (p = current) != null) {
int n = batch + BATCH_UNIT;
if (n > s)
n = s;
if (n > MAX_BATCH)
n = MAX_BATCH;
Object[] a = new Object[n];
int j = 0;
do { a[j++] = p.item; } while ((p = p.next) != null && j < n);
current = p;
batch = j;
est = s - j;
// 创建一个Spliterator。OfDouble使用定制的spliterator特征集覆盖给定数组的一系列元素。
return Spliterators.spliterator(a, 0, j, Spliterator.ORDERED);
}
return null;
}
/**
* 为当前线程中的每个剩余元素依次执行给定的操作,直到处理完所有元素或操作抛出异常为止。
* 如果这个Spliterator是有序的,那么操作将按照相遇顺序执行。由操作引发的异常被转发给调用方。
*/
public void forEachRemaining(Consumer<? super E> action) {
Node<E> p; int n;
if (action == null) throw new NullPointerException();
if ((n = getEst()) > 0 && (p = current) != null) {
current = null;
est = 0;
do {
E e = p.item;
p = p.next;
action.accept(e);
} while (p != null && --n > 0);
}
if (list.modCount != expectedModCount)
throw new ConcurrentModificationException();
}
/**
* 如果存在剩余元素,对其执行给定操作,返回true;否则返回false。
* @param action 动作
*/
public boolean tryAdvance(Consumer<? super E> action) {
Node<E> p;
if (action == null) throw new NullPointerException();
if (getEst() > 0 && (p = current) != null) {
--est;
E e = p.item;
current = p.next;
action.accept(e);// 对e执行此操作
if (list.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
return false;
}
/**
* 返回此Spliterator及其元素的一组特征。
*/
public int characteristics() {
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
}
}
参考:JDK 1.6 API
JDK 1.8 API
因篇幅问题不能全部显示,请点此查看更多更全内容