java源码分析之集合框架 LinkedList 04

时间:2022-09-09 19:35:21

LinkedList简介
首先看看LinkedList与Collection的关系:
java源码分析之集合框架 LinkedList 04

LinkedList的继承关系如下:

java.lang.Object  
↳ java.util.AbstractCollection<E>
↳ java.util.AbstractList<E>
↳ java.util.AbstractSequentialList<E>
↳ java.util.LinkedList<E>

public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
}

LinkedList是一个继承与AbatractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。

LinkedList实现了List接口,能对它进行队列操作。
LinkedList实现了Deque接口,即能将LinkedList当作双端队列使用。
LinkedList实现了java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。

LinkedList是非同步的。

这里插一句,简单说一下AbstractSequentialList,因为LinkedList是其子类。

AbstractSequentialList实现了get(int index)、set(int index, E element)、add(int index, E element)和remove(int index)这些方法。这些接口都是随机访问List的,LinkedList是双向链表,既然它继承与AbstractSequentialList,就相当于已经实现了“get(int index)”这些接口,可以支持随机访问了。

此外,如果我们需要通过AbstractSequentialList实现一个自己的列表,只需要扩展此类,并提供listIterator()和size()方法的实现即可。若要实现不可修改的列表,则需要实现列表迭代器的hashNext、next、hashPrevious、previous和index方法即可。

下面先总览一下LinkedList的构造函数和API:

//LinkedList的API 
boolean add(E object)
void add(int location, E object)
boolean addAll(Collection<? extends E> collection)
boolean addAll(int location, Collection<? extends E> collection)
void addFirst(E object)
void addLast(E object)
void clear()
Object clone()
boolean contains(Object object)
/*返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。 */
Iterator<E> descendingIterator()
E element()
E get(int location)
E getFirst()
E getLast()
int indexOf(Object object)
int lastIndexOf(Object object)
ListIterator<E> listIterator(int location)
boolean offer(E o) /*将指定元素添加到此列表的末尾(最后一个元素)。*/
boolean offerFirst(E e)
boolean offerLast(E e)
E peek() /*获取但不移除此列表的头(第一个元素)*/
E peekFirst()
E peekLast()
E poll() /*获取并移除此列表的头(第一个元素)*/
E pollFirst()
E pollLast()
E pop() /*从此列表所表示的堆栈处弹出一个元素。*/
void push(E e) /*将元素推入此列表所表示的堆栈。*/
E remove() /* 获取并移除此列表的头(第一个元素)。*/
E remove(int location)
boolean remove(Object object)
E removeFirst()
boolean removeFirstOccurrence(Object o)
E removeLast()
boolean removeLastOccurrence(Object o)
E set(int location, E object)
int size()
<T> T[] toArray(T[] contents)
Object[] toArray()

LinkedList源码分析(基于JDK1.7)
下面通过分析LinkedList的源码更加深入的了解LinkedList原理。由于LinkedList是通过双向链表实现的,所以源码也比较容易理解:

package java.util;

/*双向链表*/
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
/**
* 这里先说一下transient关键字的用法:
* 一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列
* 化模式为开发者提供了很多便利,可以不必关系具体序列化的过程,只要这个类实
* 现了Serilizable接口,这个的所有属性和方法都会自动序列化。但是有种情况是
* 有些属性是不需要序列号的,所以就用到这个关键字。只需要实现Serilizable接
* 口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属
* 性就不会序列化到指定的目的地中。
*/

transient int size = 0; //LinkedList中元素的个数
transient Node<E> first; //链表的头结点
transient Node<E> last; //链表的尾节点

public LinkedList() { //默认构造函数,创建一个空链表
}

//按照c中的元素生成一个LinkedList
public LinkedList(Collection<? extends E> c) {
this();
addAll(c); //将c中的元素添加到空链表的尾部
}

/***************************** 添加头结点 ********************************/
public void addFirst(E e) {
linkFirst(e);
}

private void linkFirst(E e) {
final Node<E> f = first; // ① 找到头结点并指向节点f
// ② 生成一个新结点e(其前向指针为null,后向指针为f)
final Node<E> newNode = new Node<>(null, e, f);
first = newNode; // ③ first指向新生成的结点(f保存着老的头结点信息)
if (f == null)
last = newNode; //如果f为null,则表示整个链表目前是空的,则尾结点也指向新结点
else
f.prev = newNode; // ④ 将原头结点的前一个节点指向新插入的节点e
size++; // ⑤ 长度加1
modCount++; //修改次数+1
}

/****************** 添加尾节点,与上面添加头结点原理一样 ******************/
public boolean add(E e) {
linkLast(e);
return true;
}
public void addLast(E e) {
linkLast(e);
}
public void add(int index, E element) {
checkPositionIndex(index);

if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}
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 ************************/
void linkBefore(E e, Node<E> succ) {
// assert succ != null; //外界调用需保证succ不为null,否则程序会抛出空指针异常
final Node<E> pred = succ.prev;
//生成一个新结点e,其前向指针指向pred,后向指针指向succ
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode; //succ的前向指针指向newNode
if (pred == null)
//如果pred为null,则表示succ为头结点,此时头结点指向最新生成的结点newNode
first = newNode;
else
//pred的后向指针指向新生成的结点,此时已经完成了结点的插入操作
pred.next = newNode;
size++;
modCount++;
}
/*********************** 返回此列表的第一个元素 *********************/
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 == null)
throw new NoSuchElementException();
return unlinkFirst(f); //private方法
}

private E unlinkFirst(Node<E> f) {
// assert f == first && f != null; //需确保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)
//如果next为null,则表示f为last结点,此时链表即为空链表
last = null;
else
//修改next的前向指针,因为first结点的前向指针为null
next.prev = null;
size--;
modCount++;
return element;
}

/********************** 删除尾节点,并返回尾节点的值 ********************/
public E removeLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l); //private方法
}

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,并返回该节点的值 ******************/
E unlink(Node<E> x) {
// assert x != null; //需确保x不为null,否则后续操作会抛出空指针异常
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.prev;

if (prev == null) {
//如果prev为空,则x结点为first结点,此时first结点指向next结点(x的后向结点)
first = next;
} else {
prev.next = next; //x的前向结点的后向指针指向x的后向结点
x.prev = null; //释放x的前向指针
}

if (next == null) {
//如果next结点为空,则x结点为尾部结点,此时last结点指向prev结点(x的前向结点)
last = prev;
} else {
next.prev = prev; //x的后向结点的前向指针指向x的前向结点
x.next = null; //释放x的后向指针
}

x.item = null; //释放x的值节点,此时x节点可以完全被GC回收
size--;
modCount++;
return element;
}

/*************** 判断元素(值为o)是否在链表中 *************/
public boolean contains(Object o) {
return indexOf(o) != -1; //定位元素
}

//返回元素个数
public int size() {
return size;
}

//向链表尾部添加元素e
public boolean add(E e) {
linkLast(e);
return true;
}

/*************** 删除值为o的元素 *************/
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 {//o不为空
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}

/*************** 将集合e中所有元素添加到链表中 *************/
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
//从index开始,向后添加的
public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index); //yi判断index是否越界

Object[] a = c.toArray(); //将集合c转换为数组
int numNew = a.length;
if (numNew == 0)
return false;

Node<E> pred, succ;
if (index == size) {//即index个节点在尾节点后面
succ = null;
pred = last; //pred指向尾节点
} else {
succ = node(index); //succ指向第index个节点
pred = succ.prev; //pred指向succ的前向节点
}

//for循环结束后,a里面的元素都添加到当前链表里了,向后添加
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null)
first = newNode; //如果pred为null,则succ为头结点
else
pred.next = newNode; //pred的后向指针指向新节点
pred = newNode; //pred指向新节点,即往后移动一个节点,用于下一次循环
}

if (succ == null) { //succ为null表示index为尾节点之后
last = pred;
} else {
//pred表示所有元素添加好之后的最后那个节点,此时pred的后向指针指向之前记录的节点,即index处的节点
pred.next = succ;
succ.prev = pred; //之前记录的结点指向添加元素之后的最后结点
}

size += numNew;
modCount++;
return true;
}

/******************** 清空链表 *************************/
public void clear() {
for (Node<E> x = first; x != null; ) {
Node<E> next = x.next;
x.item = null; //释放值结点,便于GC回收
x.next = null; //释放前向指针
x.prev = null; //释放前后指针
x = next; //后向遍历
}
first = last = null; //释放头尾节点
size = 0;
modCount++;
}


/******************* Positional Access Operations ***********************/

//获得第index个节点的值
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
/* //定位index处的节点*/
Node<E> node(int index) {
// assert isElementIndex(index);

/*index小于size右移一位(差不多是[size/2]下取整),
从头开始移动指针查找*/

if (index < (size >> 1)) {//index<size/2时
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;
}
}
//设置第index元素的值
public E set(int index, E element) {
checkElementIndex(index);
Node<E> x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
}

//在index个节点之前添加新的节点
public void add(int index, E element) {
checkPositionIndex(index);

if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}

//删除第index个节点
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}

//判断index是否为链表中的元素下标
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
}

//判断index是否为链表中的元素下标。。。包含了size
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size;
}

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));
}

/*************************** Search Operations *************************/

//返回首次出现指定元素值o的节点索引
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))
return index;
index++;
}
}
return -1; //没有则返回-1
}

/*返回最后一次出现指定元素值o的节点索引
即从尾开始查找第一次出现的位置*/

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))
return index;
}
}
return -1;
}

/***************************** Queue operations ***********************/
//下面是与栈和队列相关的操作了
//实现栈的操作,返回第一个元素的值
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item; //不删除
}

//实现队列操作,返回第一个节点
public E element() {
return getFirst();
}

//实现栈的操作,弹出第一个节点
public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f); //删除
}

//实现队列操作,删除节点
public E remove() {
return removeFirst();
}

//末尾添加节点
public boolean offer(E e) {
return add(e);
}

/************************* Deque operations **********************/
//下面都是和双端队列相关的操作了
//添加头结点
public boolean offerFirst(E e) {
addFirst(e);
return true;
}

//添加尾节点
public boolean offerLast(E e) {
addLast(e);
return true;
}

//返回头结点的值
public E peekFirst() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}

//返回尾节点的值
public E peekLast() {
final Node<E> l = last;
return (l == null) ? null : l.item;
}

//弹出头结点
public E pollFirst() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f); //删除
}

//弹出尾节点
public E pollLast() {
final Node<E> l = last;
return (l == null) ? null : unlinkLast(l); //删除
}

//栈操作,添加头结点
public void push(E e) {
addFirst(e);
}

//栈操作,删除头结点
public E pop() {
return removeFirst();
}

//删除第一次出现o的节点
public boolean removeFirstOccurrence(Object o) {
return remove(o);
}

//删除最后一次出现o的节点
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;
}

/************************* ListIterator ***********************/

public ListIterator<E> listIterator(int index) {
checkPositionIndex(index);
return new ListItr(index); //ListItr是一个双向迭代器
}

//实现双向迭代器
private class ListItr implements ListIterator<E> {
private Node<E> lastReturned = null;//用Node记录当前节点值
private Node<E> next; //链表中当前节点
private int nextIndex; //当前节点的索引
private int expectedModCount = modCount; //修改次数

ListItr(int index) {
// assert isPositionIndex(index);
/*从此处可以看出next指向node(index),即本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++; //节点索引+1
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;
}
/*从列表中移除由 next 或 previous 返回的最后一个
元素(可选操作)。*/

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++;
}
/*用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)*/
public void set(E e) { //设置当前节点的值
if (lastReturned == null)
throw new IllegalStateException();
checkForComodification();
lastReturned.item = e;
}

/*将指定的元素插入列表(可选操作)*/
public void add(E e) {
checkForComodification();
lastReturned = null;
if (next == null)
linkLast(e);
else
linkBefore(e, next);
nextIndex++;
expectedModCount++;
}

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.previous来提供前向迭代器,方向与原来相反
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();
}
}

//克隆操作,执行浅拷贝,只复制引用,没有复制引用指向的内存
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;
}

/*************************** toArray ****************************/
//返回LinkedList的Object[]数组
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;
}

//返回LinkedList的模板数组,存储在a中
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
//如果a的大小 < LinkedList的元素个数,意味着数组a不能容纳LinkedList的全部元素
//则新建一个T[]数组,T[]的大小为LinkedList大小,并将T[]赋给a
//Array.newInstance(Class<?> componentType, int length)
a = (T[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);
//如果a大小够容纳LinkedList的全部元素
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;
}

/************************* Serializable **************************/
private static final long serialVersionUID = 876323262645176354L;

//java.io.Serializable的写入函数
//将LinkedList的“容量,所有元素值”写入到输出流中
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out any hidden serialization magic
s.defaultWriteObject();

// Write out size
s.writeInt(size); //写入容量

// Write out all elements in the proper order.
for (Node<E> x = first; x != null; x = x.next) //写入所有数据
s.writeObject(x.item);
}

//java.io.Serializable的读取函数:根据写入方式反向读出
//先将LinkedList的“容量”读出,然后将“所有元素值”读出
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden serialization magic
s.defaultReadObject();

// Read in size
int size = s.readInt(); //读出容量

// Read in all elements in the proper order.
for (int i = 0; i < size; i++) //读出所有元素值
linkLast((E)s.readObject());
}
}

总结一下:
1). LinkedList是通过双向链表去实现的。
2). 从LinkedList的实现方式中可以看出,它不存在容量不足的问题,因为是链表。
3). LinkedList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写出“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。
4). LinkdedList的克隆函数,即是将全部元素克隆到一个新的LinkedList中。
5). 由于LinkedList实现了Deque,而Deque接口定义了在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。
6). LinkedList可以作为FIFO(先进先出)的队列,作为FIFO的队列时,下标的方法等价:

队列方法       等效方法  
add(e) addLast(e)
offer(e) offerLast(e)
remove() removeFirst()
poll() pollFirst()
element() getFirst()
peek() peekFirst()

7). LinkedList可以作为LIFO(后进先出)的栈,作为LIFO的栈时,下表的方法等价:

栈方法        等效方法  
push(e) addFirst(e)
pop() removeFirst()
peek() peekFirst()

LinkedList遍历方式
LinkedList支持多种遍历方式,建议不要采用随机访问的方式去遍历LinkedList,而采用逐个遍历的方式。下面我们来看看每种遍历方式:
1). 通过Iterator迭代器遍历

for(Iterator iter = list.iterator(); iter.hasNext();)  
iter.next();

2). 通过快速随机访问遍历

int size = list.size();  
for (int i=0; i<size; i++) {
list.get(i);
}

3). 通过for循环遍历

for (Integer integ:list)   
;

4). 通过pollFirst()或pollLast()来遍历

while(list.pollFirst() != null)  
;
while(list.pollLast() != null)
;

下面通过一个测试用例来测试一下这些方法的效率:

package wn.comeOn.java.containers;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.NoSuchElementException;

public class LinkedListTest {

public static void main(String[] args) {

// 通过Iterator遍历LinkedList
iteratorLinkedListByIterator(getLinkedList());

//通过快速随机访问遍历LinkedList
iteratorLinkedListByRandom(getLinkedList());

//通过for遍历LinkedList
iteratorLinkedListByFor(getLinkedList());

//通过PollFirst遍历LinkedList
iteratorLinkedListByPollFirst(getLinkedList());

//通过PollLast遍历LinkedList
iteratorLinkedListByPollLast(getLinkedList());

//通过removeFirst遍历 LinkedList
iteratorLinkedListByremoveFirst(getLinkedList());

//通过removeLast遍历 LinkedList
iteratorLinkedListByremoveLast(getLinkedList());

}

/**
* 通过removeLast遍历 LinkedList
* @param linkedList
*/

private static void iteratorLinkedListByremoveLast(LinkedList<Integer> linkedList) {

if(linkedList == null)
return ;

long start = System.currentTimeMillis();
try{
while(linkedList.removeLast() != null){
;
}
}catch(NoSuchElementException e){
}

long end = System.currentTimeMillis();
long interval = end - start;
System.out.println("iteratorLinkedListByremoveLast:" + interval + "ms");

}

/**
* 通过removeFirst遍历 LinkedList
* @param linkedList
*/

private static void iteratorLinkedListByremoveFirst(LinkedList<Integer> linkedList) {

if(linkedList == null)
return ;

long start = System.currentTimeMillis();
try{
while(linkedList.removeFirst() != null){
;
}
}catch(NoSuchElementException e){
}

long end = System.currentTimeMillis();
long interval = end - start;
System.out.println("iteratorLinkedListByremoveFirst:" + interval + "ms");

}

/**
* 通过PollLast遍历LinkedList
* @param linkedList
*/

private static void iteratorLinkedListByPollLast(LinkedList<Integer> linkedList) {

if(linkedList == null)
return ;

long start = System.currentTimeMillis();
while(linkedList.pollLast() != null){
;
}
long end = System.currentTimeMillis();
long interval = end - start;
System.out.println("iteratorLinkedListByPollFirst:" + interval + "ms");

}

/**
* 通过PollFirst遍历LinkedList
* @param linkedList
*/

private static void iteratorLinkedListByPollFirst(LinkedList<Integer> linkedList) {

if(linkedList == null)
return ;

long start = System.currentTimeMillis();
while(linkedList.pollFirst() != null){
;
}
long end = System.currentTimeMillis();
long interval = end - start;
System.out.println("iteratorLinkedListByPollFirst:" + interval + "ms");

}

/**
* 通过for遍历LinkedList
* @param object
*/

private static void iteratorLinkedListByFor(LinkedList<Integer> linkedList) {

if(linkedList == null)
return ;

long start = System.currentTimeMillis();
for(Integer i : linkedList){
;
}
long end = System.currentTimeMillis();
long interval = end - start;
System.out.println("iteratorLinkedListByFor:" + interval + "ms");


}

/**
* 通过快速随机访问遍历LinkedList
* @param linkedList
*/

private static void iteratorLinkedListByRandom(LinkedList<Integer> linkedList) {

if(linkedList == null)
return ;

long start = System.currentTimeMillis();
int size = linkedList.size();
for(int i=0 ;i < size ; i++){
linkedList.get(i);
}
long end = System.currentTimeMillis();
long interval = end - start;
System.out.println("iteratorLinkedListByRandom:" + interval + "ms");

}

/**
* 通过Iterator遍历LinkedList
* @param linkedList
*/

private static void iteratorLinkedListByIterator(LinkedList<Integer> linkedList) {

if(linkedList == null){
return ;
}
long start = System.currentTimeMillis();

for( Iterator<Integer> iter = linkedList.iterator(); iter.hasNext();){
iter.next();
}
long end = System.currentTimeMillis();
long interval = end - start;

long start1 = System.currentTimeMillis();
Iterator iter1 = linkedList.iterator();
while(iter1.hasNext()){
iter1.next();
}
long end1 = System.currentTimeMillis();
long interval1 = end1 - start1;

System.out.println("iteratorLinkedListByIterator:" + interval+"ms," + interval1 + "ms");
}

private static LinkedList<Integer> getLinkedList() {

LinkedList<Integer> lists = new LinkedList<Integer>();

for(int i=0 ; i < 500000 ; i++){
lists.addLast(i);
}

return lists;
}

}

测试结果如下:

iteratorLinkedListByIterator:12ms,6ms
iteratorLinkedListByRandom:405009ms
iteratorLinkedListByFor:10ms
iteratorLinkedListByPollFirst:5ms
iteratorLinkedListByPollFirst:7ms
iteratorLinkedListByremoveFirst:4ms
iteratorLinkedListByremoveLast:7ms

由此可见,遍历LinkedList时,使用removeFirst(),removeLast()或pollFirst(),pollLast()效率最高(jvm不同可能结果有差异,但是大体都是这几个快)。但是用它们遍历会删除原始数据;若只是单纯的取数据,而不删除,建议用迭代器方式或者for-each方式。

无论如何,千万不要用随机访问去遍历LinkedList!除非脑门儿被驴给踢了… …