上一章学习了ArrayList,并分析了其源码,这一章我们将对LinkedList的具体实现进行详细的学习。依然遵循上一章的步骤,先对LinkedList有个整体的认识,然后学习它的源码,深入剖析LinkedList。
LinkedList简介
首先看看LinkedList与Collection的关系:
LinkedList的继承关系如下:
[java] view plain copy
- 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:
[java] view plain copy
- 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包含三个重要的成员:first、last和size:first是双向链表的表头,last是双向链表的尾节点,size是双向链表中的节点个数。
LinkedList源码分析(基于JDK1.7)
下面通过分析LinkedList的源码更加深入的了解LinkedList原理。由于LinkedList是通过双向链表实现的,所以源码也比较容易理解:
[java] view plain copy
- 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;
- size++;
- modCount++; //修改次数+1
- }
- /****************** 添加尾节点,与上面添加头结点原理一样 ******************/
- public void addLast(E e) {
- linkLast(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 ************************/
- 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 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;
- }
- /********************** 获得头结点的值 ********************/
- 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;
- }
- /*************** 判断元素(值为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); //判断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元素的值
- 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));
- }
- //定位index处的节点
- Node<E> node(int index) {
- // assert isElementIndex(index);
- //index<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 *************************/
- //返回首次出现指定元素值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;//记录当前节点信息
- 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++; //节点索引+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;
- }
- 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++;
- }
- 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
- 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;
- }
- private static final long serialVersionUID = 876323262645176354L;
- /************************* Serializable **************************/
- //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的队列时,下标的方法等价:
[java] view plain copy
- 队列方法 等效方法
- add(e) addLast(e)
- offer(e) offerLast(e)
- remove() removeFirst()
- poll() pollFirst()
- element() getFirst()
- peek() peekFirst()
7). LinkedList可以作为LIFO(后进先出)的栈,作为LIFO的栈时,下表的方法等价:
[java] view plain copy
- 栈方法 等效方法
- push(e) addFirst(e)
- pop() removeFirst()
- peek() peekFirst()
LinkedList遍历方式
LinkedList支持多种遍历方式,建议不要采用随机访问的方式去遍历LinkedList,而采用逐个遍历的方式。下面我们来看看每种遍历方式:
1). 通过Iterator迭代器遍历
[java] view plain copy
- for(Iterator iter = list.iterator(); iter.hasNext();)
- iter.next();
2). 通过快速随机访问遍历
[java] view plain copy
- int size = list.size();
- for (int i=0; i<size; i++) {
- list.get(i);
- }
3). 通过for循环遍历
[java] view plain copy
- for (Integer integ:list)
- ;
4). 通过pollFirst()或pollLast()来遍历
[java] view plain copy
- while(list.pollFirst() != null)
- ;
- while(list.pollLast() != null)
- ;
5). 通过removeFirst()或removeLast()来遍历
[java] view plain copy
- while(list.removeFirst() != null)
- ;
- while(list.removeLast() != null)
- ;
下面通过一个测试用例来测试一下这些方法的效率:
[java] view plain copy
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.NoSuchElementException;
- /*
- * @description 测试LinkedList的几种遍历方式和效率
- * @author eson_15
- */
- public class LinkedListThruTest {
- public static void main(String[] args) {
- // 通过Iterator遍历LinkedList
- iteratorLinkedListThruIterator(getLinkedList()) ;
- // 通过快速随机访问遍历LinkedList
- iteratorLinkedListThruForeach(getLinkedList()) ;
- // 通过for循环的变种来访问遍历LinkedList
- iteratorThroughFor2(getLinkedList()) ;
- // 通过PollFirst()遍历LinkedList
- iteratorThroughPollFirst(getLinkedList()) ;
- // 通过PollLast()遍历LinkedList
- iteratorThroughPollLast(getLinkedList()) ;
- // 通过removeFirst()遍历LinkedList
- iteratorThroughRemoveFirst(getLinkedList()) ;
- // 通过removeLast()遍历LinkedList
- iteratorThroughRemoveLast(getLinkedList()) ;
- }
- private static LinkedList<Integer> getLinkedList() {
- LinkedList<Integer> llist = new LinkedList<Integer>();
- for (int i=0; i<500000; i++)
- llist.addLast(i);
- return llist;
- }
- /**
- * 通过快迭代器遍历LinkedList
- */
- private static void iteratorLinkedListThruIterator(LinkedList<Integer> list) {
- if (list == null)
- return ;
- long start = System.currentTimeMillis();
- for(Iterator<Integer> iter = list.iterator(); iter.hasNext();)
- iter.next();
- long end = System.currentTimeMillis();
- long interval = end - start;
- System.out.println("iteratorLinkedListThruIterator:" + interval+" ms");
- }
- /**
- * 通过快速随机访问遍历LinkedList
- */
- private static void iteratorLinkedListThruForeach(LinkedList<Integer> list) {
- if (list == null)
- return ;
- long start = System.currentTimeMillis();
- int size = list.size();
- for (int i=0; i<size; i++) {
- list.get(i);
- }
- long end = System.currentTimeMillis();
- long interval = end - start;
- System.out.println("iteratorLinkedListThruForeach:" + interval+" ms");
- }
- /**
- * 通过另外一种for循环来遍历LinkedList
- */
- private static void iteratorThroughFor2(LinkedList<Integer> list) {
- if (list == null)
- return ;
- long start = System.currentTimeMillis();
- for (Integer integ : list)
- ;
- long end = System.currentTimeMillis();
- long interval = end - start;
- System.out.println("iteratorThroughFor2:" + interval+" ms");
- }
- /**
- * 通过pollFirst()来遍历LinkedList
- */
- private static void iteratorThroughPollFirst(LinkedList<Integer> list) {
- if (list == null)
- return ;
- long start = System.currentTimeMillis();
- while(list.pollFirst() != null)
- ;
- long end = System.currentTimeMillis();
- long interval = end - start;
- System.out.println("iteratorThroughPollFirst:" + interval+" ms");
- }
- /**
- * 通过pollLast()来遍历LinkedList
- */
- private static void iteratorThroughPollLast(LinkedList<Integer> list) {
- if (list == null)
- return ;
- long start = System.currentTimeMillis();
- while(list.pollLast() != null)
- ;
- long end = System.currentTimeMillis();
- long interval = end - start;
- System.out.println("iteratorThroughPollLast:" + interval+" ms");
- }
- /**
- * 通过removeFirst()来遍历LinkedList
- */
- private static void iteratorThroughRemoveFirst(LinkedList<Integer> list) {
- if (list == null)
- return ;
- long start = System.currentTimeMillis();
- try {
- while(list.removeFirst() != null)
- ;
- } catch (NoSuchElementException e) {
- }
- long end = System.currentTimeMillis();
- long interval = end - start;
- System.out.println("iteratorThroughRemoveFirst:" + interval+" ms");
- }
- /**
- * 通过removeLast()来遍历LinkedList
- */
- private static void iteratorThroughRemoveLast(LinkedList<Integer> list) {
- if (list == null)
- return ;
- long start = System.currentTimeMillis();
- try {
- while(list.removeLast() != null)
- ;
- } catch (NoSuchElementException e) {
- }
- long end = System.currentTimeMillis();
- long interval = end - start;
- System.out.println("iteratorThroughRemoveLast:" + interval+" ms");
- }
- }
测试结果如下:
[java] view plain copy
- iteratorLinkedListThruIterator:10 ms
- iteratorLinkedListThruForeach:414648 ms
- iteratorThroughFor2:10 ms
- iteratorThroughPollFirst:8 ms
- iteratorThroughPollLast:10 ms
- iteratorThroughRemoveFirst:7 ms
- iteratorThroughRemoveLast:6 ms
由此可见,遍历LinkedList时,使用removeFirst()或removeLast()效率最高。但是用它们遍历会删除原始数据;若只是单纯的取数据,而不删除,建议用迭代器方式或者for-each方式。
无论如何,千万不要用随机访问去遍历LinkedList!除非脑门儿被驴给踢了... ...
LinkedList源码就讨论这么多,如果错误,欢迎留言指正~
转载:http://blog.csdn.net/eson_15/article/details/51135944