目录
简介
LinkedList底层是基于双向链表实现,从源码(jdk1.8)看不是循环双向链表(循环双向链表即链表与头结点与尾节点相连)。可以当做栈,队列和双端队列来使用。线程是非安全的,适合单线程使用。
LinkedList实现了接口List,可以进行队列的操作;实现了接口Deque,可以当做双端队列使用;实现Cloneable接口,能克隆;实现java.io.Serializable接口,支持序列化并能通过序列化去传输。
由于底层是链表结构,在执行删除和插入操作时效率比较高,但链表没有索引,所以随机访问操作方面效率低下。
介绍
1.构造方法
public LinkedList() {}
public LinkedList(Collection<? extends E> c) {}
- 构建一个空的LinkedList。
- 构建一个包含了集合c中所有元素的LinkedList。
2.内部变量
transient int size = 0;
transient Node<E> first;
transient Node<E> last;
- size----LinkedList中的元素的总数。
- first----底层双向链表中第一个节点(头结点)。
- last----底层双向链表中最后一个节点(尾节点)。
3.内部方法
修饰符 | 返回值类型 | 方法 | 功能 |
---|---|---|---|
public | E | getFirst() | 返回LinkedList中的第一个元素,列表为空,将抛出NoSuchElementException异常。 |
public | E | getLast() | 返回LinkedList中的最后一个元素,列表为空,将抛出NoSuchElementException异常。 |
public | E | removeFirst() | 移除和并返回LinkedList中第一个元素,列表为空,将抛出NoSuchElementException异常。 |
public | E | removeLast() | 移除和返回LinkedList中的最后一个元素,列表为空,将抛出NoSuchElementException异常。 |
public | void | addFirst(E e) | 向LinkedList中起初位置添加指定的元素 |
public | void | addLast(E e) | 向LinkedList末尾添加指定的元素 |
public | boolean | contains(Object o) | 如果LinkedList中包含指定的元素,则返回true. |
public | int | size() | 返回LinkedList中元素总数 |
public | boolean | add(E e) | 添加指定的元素到LinkedList的末尾。等价于addLast()方法,区别是后者没有返回值 |
public | boolean | remove(Object o) | 移除LinkedList中首次出现的指定元素,不包含指定元素返回false |
public | boolean | addAll(Collection<? extends E> c) | 向LinkedList末尾添加集合c中所有元素,指定集合c为null,将抛出NullPointerException异常。 |
public | boolean | addAll(int index, Collection<? extends E> c) | 向LinkedList插入集合c中所有元素,位置从index开始,指定集合c为null,将抛出NullPointerException异常。 |
public | void | clear() | 移除LinkedList所有元素,LinkedList清空 |
索引位置访问操作 | |||
public | E | get(int index) | 获取LinkedList中指定索引的元素 |
public | E | set(int index, E element) | 用指定的元素替换LinkedList中指定索引位置的元素 |
public | void | add(int index, E element) | 向LinkedList中指定索引位置插入指定的元素element |
public | E | remove(int index) | 移除和返回LinkedList中指定索引位置的元素 |
public | int | indexOf(Object o) | 返回LinkedList中首次出现指定元素的索引。不包含指定元素,返回-1 |
public | int | lastIndexOf(Object o) | 返回LinkedList中最后一个出现指定元素的索引。不包含指定元素,返回-1 |
队列的相关操作 | |||
public | E | peek() | 获取LinkedList中的第一个元素。列表为空时,将返回null |
public | E | element() | 获取LinkedList的第一个元素。列表为空时,将抛出NoSuchElementException异常 |
public | E | poll() | 返回并移除LinkedList中的第一个元素。列表为空时,将返回null |
public | E | remove() | 返回并移除列表中的第一个元素,列表为空时,将抛出NoSuchElementException异常 |
public | boolean | offer(E e) | 添加指定的元素到LinkedList末尾 |
双端队列的相关操作 | |||
public | boolean | offerFirst(E e) | 向LinkedList中头部插入指定的元素,底层调用addFirst() |
public | boolean | offerLast(E e) | 向LinkedList末尾插入指定的元素,底层调用addLast() |
public | E | peekFirst() | 返回LinkedList中的第一个元素,如果LinkedList为空时,返回null |
public | E | peekLast() | 返回LinkedList中第后一个元素,如果LinkedList为空时,返回null |
public | E | pollFirst() | 返回和移除LinkedList中第一个元素,如果LinkedList为空时,返回null |
public | E | pollLast() | 返回和移除LinkedList中的最后一个元素,如果LinkedList为空时,返回null |
public | void | push(E e) | 向LinkedList表示的栈中压入一个元素,即向LinkedList起始位置插入一个元素。 |
public | E | pop() | 从LinkedList表示的栈中弹出一个元素,即移除和返回LinkedList中的第一个元素。列表为空,将抛出NoSuchElementException异常。 |
public | boolean | removeFirstOccurrence(Object o) | 移除LinkedList中首次出现的指定元素,底层调用remove()方法 |
public | boolean | removeLastOccurrence(Object o) | 移除LinkedList中最后出现的指定元素 |
其他操作 | |||
public | ListIterator<E> | listIterator(int index) | 返回LinkedList从指定索引index开始的所有元素的迭代器ListIterator |
public | Iterator<E> | descendingIterator() | 返回反向迭代的迭代器 |
public | Object clone() | clone() | 返回LinedList的浅度复制的实例 |
public | Object[] | toArray() | 按适当的顺序返回(从第一个到最后一个元素)包含LinkedList中所有元素的数组 |
public | <T> T[] | toArray(T[] a) | 按适当的顺序返回(从第一个到最后一个元素)包含LinkedList中所有元素的数组,并且返回数组的运行类型是指定的数组类型 |
源码分析(基于jdk1.8)
关于LinkedList源码的几点说明:
1)modCount是用来记录修改次数,由于LinkedList是非线程安全的,任何对LInkedList的修改都会modCount++操作。迭代器迭代初始化时会将modCount赋值给 expectedModCount。在迭代过程中,会判断 modCount是否等于 expectedModCount,如果不等,说明其他线程修改了LinkedList,就会抛出ConcurrentModificationException异常。
2)LinkedList是双向链表结构,Node表示的是每个节点,每个Node节点包含了上个节点(前驱指针)和下个节点(后驱指针)以及本节点的元素。需要注意的是头结点前驱指针为null,尾节点后驱指针为null。
private static class Node<E> {
E item;//包含元素
Node<E> next;//后驱指针/节点
Node<E> prev;//前驱指针/节点
}
3)链表的操作:
a.删除节点:当删除其中一个节点时,总体思想是将本节点删除,然后让删除节点的上个节点和下个节点互相关联。删除本节点需要将本节点包含的前驱指针和后驱指针以及元素全部置为null(GC回收本节点),如图:
b. 添加节点:当在某个索引位置或者链表的尾部添加节点时,总体思想就是创建一个新节点,新节点中前驱指针是插入位置的上个节点,新节点中后驱指针是就是插入位置之前的节点,设置新节点的元素。由于需要双向链表,需要将上个节点后驱指针指向新节点,将之前插入位置的节点的前驱指针指向新节点。如图:
3)LinkedList底层是双向链表,并没有像数组一样有索引概念,之所以能通过index访问是通过从头节点或者尾部节点开始遍历计数,计数等于index时回对应的节点。所以LinkedList随机访问速度很慢,而删除和插入速度较快,是因为直接关联对应的节点就可以,不像ArrayList在删除和插入操作时,需要将整个数组复制到新数组中
4)LinkedList中根据索引index获取节点时,进行了优化,将index与长度size的一半比较,如果index<size/2(源码中通过size>>1实现,位操作比数学运算快),就只从位置0往后遍历到位置index处,而如果index>size/2,就只从位置size往前遍历到位置index处。这样可以减少一部分不必要的遍历。
5)关于addAll(int index,Collection<? extends E> c)方法源码,需要知道原先index位置的节点会被移动到插入集合的后面,具体思想是在将集合c转换成数组,循环数组,第一次循环时,创建新节点,新节点的前驱指针指向了原先index位置的上个节点,没有指定后驱指针,而是在第二次循环时,重新创建的新节点,之前的新节点成了上个节点,然后才指定上次新节点后驱指正指向本次循环的新节点。
public class LinkedList<E> extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
//LinkedList中元素的个数
transient int size = 0;
//Invariant: (first == null && last == null) || (first.prev == null && first.item != null)
//链表中的第一个节点(头节点)
transient Node<E> first;
//Invariant: (first == null && last == null) || (last.next == null && last.item != null)
//链表中最后一个节点(尾节点)
transient Node<E> last;
//构造一个空的LinkedList
public LinkedList() {
}
//构造一个包含了指定集合c中所有元素的LinkedList.
//指定集合c如果为null,将会抛出NullPointerException异常。
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
//链表起始位置插入元素,步骤就是创建一个新节点,将之前的头节点前驱指针指向新节点.
//并且将新节点的后驱指针指向之前的第一个节点.
private void linkFirst(E e) {
final Node<E> f = first;
//新节点的前驱指针是null,后驱指针是之前的第一个节点。
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
//原先的头结点如果为null,表示新节点没有后驱节点,新节点是最后一个节点。
if (f == null)
last = newNode;
else
//将之前的头结点前驱指针指向新节点
f.prev = newNode;
size++;
modCount++;
}
//链表末尾添加元素,步骤就是创建一个新节点,新节点的前驱节点指向原先最后一个节点,后驱节点为null,
//将之前的最后一个节点后驱指针指向新节点。
void linkLast(E e) {
final Node<E> l = last;
//创建新节点,新节点的前驱节点是原先最后一个节点,后驱指针是null.
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
//原先的尾节点如果为null,表示新节点没有前驱节点,新节点成了头节点。
if (l == null)
first = newNode;
else
//将之前的最后一个节点后驱指针指向新节点
l.next = newNode;
size++;
modCount++;
}
//在非空节点succ前插入一个元素,总体思想是创建一个新节点,新节点的前驱指针指向succ节点原先的上个节点。
//succ节点原先的上个节点同样需要指向新节点,新节点后驱指针指向succ,succ的前驱指针同样需要指向新节点。
//succ.prev---->---<-newNode->---<----succ
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
//创建新节点,前驱节点指向succ节点的上个节点,后驱节点指向节点succ
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
//pred为null表明,succ的是头节点,设置新节点是头结点
if (pred == null)
first = newNode;
else
//succ节点的原先上个节点指向新节点
pred.next = newNode;
size++;
modCount++;
}
//移除非空的第一个节点,总体思想是将头结点的后驱指针和包含的元素置为null(GC回收本节点).
//头结点的前驱指针本身为null,下个节点成了头结点,需要将下个节点的前驱指针置为null。
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;
//头后驱节点为null,表明链表中只包含一个节点(即当前节点f)。
//移除本节点,就没有尾部节点
if (next == null)
last = null;
else
//后驱节点成了第一个节点,但第一个节点没有前驱节点,所以置空。
next.prev = null;
size--;
modCount++;
//返回被移除节点的元素。
return element;
}
//移除最后一个非空的节点,总体思想是将尾节点的前驱指针和包含元素置为null(GC回收本节点).
//后驱指针本身为null,上个节点成了最后一个节点,将上个节点的后驱指针置为null。
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;
//如果本节点的前驱节点为null,表明链表中只包含一个节点(即当前节点l)。
//移除本节点,就没有头节点。
if (prev == null)
first = null;
else
//上个节点成了最后一个节点,因为最后一个节点没有后驱节点,所以置为null。
prev.next = null;
size--;
modCount++;
//返回被移除节点的元素。
return element;
}
/**
* Unlinks non-null node x.
*/
//移除一个非空的节点,总体思想是,将上个节点的后驱指针指向下个节点
//下个节点的前驱指针指向上个节点,将当前节点的前驱指针和后驱指针以及元素置为null(GC回收本节点).
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;
//prev为null表示当前节点是首节点,移除当前节点,下个节点成了首节点。
if (prev == null) {
first = next;
} else {
//将上个节点的后驱指针指向下个节点
//并置空当前节点的前驱指针
prev.next = next;
x.prev = null;
}
//next为null表示当前节点是尾节点,移除当前节点,上个节点成了尾节点。
if (next == null) {
last = prev;
} else {
//将下个节点的前驱指针指向上个节点
//并将当前节点的后驱指针置为null。
next.prev = prev;
x.next = null;
}
//将当前节点的元素置为null.
x.item = null;
size--;
modCount++;
//返回被移除节点的元素。
return element;
}
//返回LinkedList中的第一个元素
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
//返回LinkedList中的最后一个元素
public E getLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return l.item;
}
//移除和并返回LinkedList中第一个元素
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
//移除和返回LinkedList中的最后一个元素
public E removeLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
}
//向LinkedList中起初位置添加指定的元素。
public void addFirst(E e) {
linkFirst(e);
}
//向LinkedList末尾添加指定的元素
public void addLast(E e) {
linkLast(e);
}
//如果LinkedList中包含指定的元素,则返回true.
public boolean contains(Object o) {
return indexOf(o) != -1;
}
//返回LinkedList中元素总数。
public int size() {
return size;
}
//添加指定的元素到LinkedList的末尾。等价于addLast()方法,区别是后者没有返回值。
public boolean add(E e) {
linkLast(e);
return true;
}
//移除LinkedList中首次出现的指定元素,不包含指定元素返回false.
public boolean remove(Object o) {
//正向遍历,寻找指定元素为null的情况
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
//正向遍历,寻找指定元素不为null的情况。
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
//向LinkedList末尾添加集合c中所有元素。
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
//向LinkedList插入集合c中所有元素,位置从index开始。总体思想是
//遍历数组a,创建新节点,新节点前驱指针指向上个节点,后驱指针不在创建的指定,而是下次循环的时候
//获取上个节点的后驱指针指向当前重新创建的新节点
//...succ----------
//...newNode<--->newNode2<--->newNode3---<---->--succ
public boolean addAll(int index, Collection<? extends E> c) {
//检查索引有效性
checkPositionIndex(index);
//返回包含LinkedList所有元素的数组
Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0)
return false;
Node<E> pred, succ;
//index==size,表示向LinkeList末尾添加
if (index == size) {
succ = null;
pred = last;
} else {
//获取索引index对应节点,以及其前驱指针
succ = node(index);
pred = succ.prev;
}
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
//创建新节点,新节点前驱指针指向之前index位置的上个节点
Node<E> newNode = new Node<>(pred, e, null);
//如果index位置上个节点为null,新节点就是头结点
if (pred == null)
first = newNode;
else
//否则index位置上个节点后驱指针指向新节点
pred.next = newNode;
pred = newNode;
}
//如果之前index位置的节点为null,循环创建的最后一个节点就是尾节点
if (succ == null) {
last = pred;
} else {
//否则将循环中创建的最后一个节点后驱指针指向之前index位置的节点
//之前index位置的节点前驱指针也需要指向之前循环创建的最后一节点。
pred.next = succ;
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}
//移除LinkedList所有元素,LinkedList清空
public void clear() {
// Clearing all of the links between nodes is "unnecessary", but:
// - helps a generational GC if the discarded nodes inhabit
// more than one generation
// - is sure to free memory even if there is a reachable Iterator
//需要将每个节点包含的前驱指针和后驱指针以及元素置为null(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++;
}
// Positional Access Operations
//*********************************//
//位置访问操作
//获取LinkedList中指定索引的元素
public E get(int index) {
//检查索引index有效性
checkElementIndex(index);
return node(index).item;
}
//用指定的元素替换LinkedList中指定索引位置的元素
public E set(int index, E element) {
//检查索引有效性
checkElementIndex(index);
//获取对应索引的节点
Node<E> x = node(index);
//获取原先的元素
E oldVal = x.item;
//用指定元素element替换
x.item = element;
//返回原先的值
return oldVal;
}
//向LinkedList中指定索引位置插入指定的元素element。
public void add(int index, E element) {
//检查索引有效性
checkPositionIndex(index);
//如果索引等于size,将元素添加LinkedList末尾
if (index == size)
linkLast(element);
else
//否则创建新节点添加到指定索引的节点前面
linkBefore(element, node(index));
}
//移除和返回LinkedList中指定索引位置的元素
public E remove(int index) {
//检查索引有效性
checkElementIndex(index);
return unlink(node(index));
}
//返回指定索引是否存在
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
}
//是否有效的索引位置
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size;
}
//构建抛出异常IndexOutOfBoundsException的具体信息
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}
//检查索引的有效性
private void checkElementIndex(int index) {
if (!isElementIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//检查索引的有效性
private void checkPositionIndex(int index) {
if (!isPositionIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//返回指定索引出的非空节点
Node<E> node(int index) {
// assert isElementIndex(index);
//index小于size/2(size>>1结果是size/2,因为位操作速度较快)
//正向遍历
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
//如果index>=size/2,逆向遍历
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
// Search Operations
//返回LinkedList中首次出现指定元素的索引。不包含指定元素,返回-1.
public int indexOf(Object o) {
int index = 0;
if (o == null) {
//如果o为null,正向遍历,返回对应索引。
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null)
return index;
index++;
}
//如果o不为null,正向遍历,返回对应的索引。
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
//不包含指定元素,返回-1.
return -1;
}
//返回LinkedList中最后一个出现指定元素的索引。不包含指定元素,返回-1。
public int lastIndexOf(Object o) {
int index = size;
//如果o为null,逆向遍历,返回对应索引
if (o == null) {
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (x.item == null)
return index;
}
//如果o不为null,逆向遍历,返回对应索引。
} else {
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (o.equals(x.item))
return index;
}
}
//不包含指定元素,返回-1.
return -1;
}
// Queue operations.
//队列的相关操作
//****************************************//
//获取LinkedList中的第一个元素。列表为空时,将返回null.
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
//获取LinkedList的第一个元素。列表为空时,将抛出NoSuchElementException异常
public E element() {
return getFirst();
}
//返回并移除LinkedList中的第一个元素。列表为空时,将返回null.
public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
//返回并移除列表中的第一个元素,列表为空时,将抛出NoSuchElementException异常。
public E remove() {
return removeFirst();
}
//添加指定的元素到LinkedList末尾。
public boolean offer(E e) {
return add(e);
}
// Deque operations
//双端队列的相关操作
//****************************************//
//向LinkedList中头部插入指定的元素,底层调用addFirst().
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
//向LinkedList末尾插入指定的元素,底层调用addLast().
public boolean offerLast(E e) {
addLast(e);
return true;
}
//返回LinkedList中的第一个元素,如果LinkedList为空时,返回null。
public E peekFirst() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
//返回LinkedList中第后一个元素,如果LinkedList为空时,返回null.
public E peekLast() {
final Node<E> l = last;
return (l == null) ? null : l.item;
}
//返回和移除LinkedList中第一个元素。
public E pollFirst() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
//返回和移除LinkedList中的最后一个元素。
public E pollLast() {
final Node<E> l = last;
return (l == null) ? null : unlinkLast(l);
}
//向LinkedList表示的栈中压入一个元素,即向LinkedList起始位置插入一个元素。
public void push(E e) {
addFirst(e);
}
//从LinkedList表示的栈中弹出一个元素,即移除和返回LinkedList中的第一个元素。
//LinkedList为空时,将会抛出NoSuchElementException异常。
public E pop() {
return removeFirst();
}
//移除LinkedList中首次出现的指定元素,底层调用remove()方法
public boolean removeFirstOccurrence(Object o) {
return remove(o);
}
//移除LinkedList中最后出现的指定元素
public boolean removeLastOccurrence(Object o) {
if (o == null) {
//如果o为null,逆向遍历,删除第一个为null的元素。
for (Node<E> x = last; x != null; x = x.prev) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
//如果o不为null,逆向遍历,删除第一个不为null的指定元素。
for (Node<E> x = last; x != null; x = x.prev) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
//不包含指定元素,返回false.
return false;
}
//返回LinkedList从指定索引index开始的所有元素的迭代器ListIterator.
public ListIterator<E> listIterator(int index) {
//检查索引位置
checkPositionIndex(index);
return new ListItr(index);
}
//内部类,用于专门迭代List集合的迭代器ListIterator.
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;
}
//是否存在下个元素
public boolean hasNext() {
return nextIndex < size;
}
//获取下一个元素
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.item;
}
//是否存在上个元素
public boolean hasPrevious() {
return nextIndex > 0;
}
//获取上个元素
public E previous() {
//检查并发修改的情况
checkForComodification();
if (!hasPrevious())
throw new NoSuchElementException();
lastReturned = next = (next == null) ? last : next.prev;
nextIndex--;
return lastReturned.item;
}
//获取下个元素的索引位置
public int nextIndex() {
return nextIndex;
}
//返回上个元素的索引位置
public int previousIndex() {
return nextIndex - 1;
}
//移除当前迭代的元素。
public void remove() {
checkForComodification();
if (lastReturned == null)
throw new IllegalStateException();
Node<E> lastNext = lastReturned.next;
unlink(lastReturned);
if (next == lastReturned)
next = lastNext;
else
nextIndex--;
lastReturned = null;
expectedModCount++;
}
//设置当前节点的元素为e
public void set(E e) {
if (lastReturned == null)
throw new IllegalStateException();
checkForComodification();
lastReturned.item = e;
}
//将元素e添加到当前节点的前面位置
public void add(E e) {
checkForComodification();
lastReturned = null;
if (next == null)
linkLast(e);
else
linkBefore(e, next);
nextIndex++;
expectedModCount++;
}
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (modCount == expectedModCount && nextIndex < size) {
action.accept(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;
}
}
//返回反向迭代的迭代器
public Iterator<E> descendingIterator() {
return new DescendingIterator();
}
//返回反向迭代的迭代器(实际是通过适配到ListItr来实现的)
private class DescendingIterator implements Iterator<E> {
private final ListItr itr = new ListItr(size());
public boolean hasNext() {
return itr.hasPrevious();
}
public E next() {
return itr.previous();
}
public void remove() {
itr.remove();
}
}
@SuppressWarnings("unchecked")
private LinkedList<E> superClone() {
try {
return (LinkedList<E>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
//返回LinedList的浅度复制的实例
public Object clone() {
LinkedList<E> clone = superClone();
// Put clone into "virgin" state
clone.first = clone.last = null;
clone.size = 0;
clone.modCount = 0;
// Initialize clone with our elements
//遍历,将元素添加到克隆的集合中
for (Node<E> x = first; x != null; x = x.next)
clone.add(x.item);
return clone;
}
//按适当的顺序返回(从第一个到最后一个元素)包含LinkedList中所有元素的数组
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
//正向遍历,将LinkedList中所有元素添加到数组result中
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
//返回数组result.
return result;
}
//按适当的顺序返回(从第一个到最后一个元素)包含LinkedList中所有元素的数组
//并且返回数组的运行类型是指定的数组类型
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
//如果数组a的长度小于size,表示数组a无法容纳LinkedList中的所有元素
//所以利用反射创建了长度为size的数组a以容纳LinkedList中元素。
if (a.length < size)
a = (T[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);
int i = 0;
Object[] result = a;
//将LinkedList中的元素添加到数组a中
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
//如果数组的a的长度的大于LinkedList中的元素的总数,将多余的空间全部置为null。
if (a.length > size)
a[size] = null;
//返回数组a.
return a;
}
//序列化ID
private static final long serialVersionUID = 876323262645176354L;
//将LinkedList的当前状态写到流中(包含非静态和非transient修饰字段,元素数量,以及每个元素)
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out any hidden serialization magic
//向流中写入非静态的非transient修饰的字段
s.defaultWriteObject();
//向流中写入LinkedList元素总数
// Write out size
s.writeInt(size);
//按照顺序将LinkedList中的所有元素写到流中
// Write out all elements in the proper order.
for (Node<E> x = first; x != null; x = x.next)
s.writeObject(x.item);
}
//重新构建LinkedList实例,先从流中读取类中非静态和非transient修饰的字段,然后读取元素的数量,最后读取所有的元素(反序列化)
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden serialization magic
//从流中读取类包含的非静态和非transient修饰的字段
s.defaultReadObject();
//从流中读取LinkedList元素总数。
int size = s.readInt();
//读取所有的元素。
for (int i = 0; i < size; i++)
linkLast((E)s.readObject());
}
....//省略了部分源码
}
案例
public class testLinedList {
public static void main(String[] args) {
//测试linkedList作为队列使用,先进先出(FIFO)
testLinkedListasQueue();
//测试LinkedList作为栈使用,先进后出(LIFO);
testLinkedListasStack();
}
//将LinkedList作为队列使用
public static void testLinkedListasQueue() {
Queue<Integer> queue1= new LinkedList<>();
for(int i = 1 ; i<=10;i++) {
queue1.offer(i);
}
printQ(queue1);
Queue<Character> queue2 = new LinkedList<>();
for(char c:"helloworld".toCharArray()) {
queue2.offer(c);
}
printQ(queue2);
}
//将LinkedList作为栈使用
public static void testLinkedListasStack() {
LinkedList<Integer> stack1 = new LinkedList<>();
for(int i = 1 ; i<=10;i++) {
stack1.push(i);
}
printS(stack1);
LinkedList<Character> stack2 = new LinkedList<>();
for(char c:"helloworld".toCharArray()) {
stack2.push(c);
}
printS(stack2);
}
//打印LinkedList中元素
private static void printS(LinkedList list) {
while(list.peek()!=null) {
System.out.print(list.pop()+" ");
}
System.out.println();
}
//打印队列元素
private static void printQ(Queue queue) {
while(queue.peek()!=null) {
System.out.print(queue.remove()+" ");
}
System.out.println();
}
}
测试结果:
1 2 3 4 5 6 7 8 9 10
h e l l o w o r l d
10 9 8 7 6 5 4 3 2 1
d l r o w o l l e h