遍历集合元素,使用迭代器或forEach遍历,尽量避免使用for循环

测试代码:

public static void main(String[] args) {

        List<String> arrayList = new ArrayList<String>();
        List<String> linkedList = new LinkedList<String>();

        for(long i=0; i<100000; i++){
            arrayList.add(""+i);
            linkedList.add(""+i);
        }

/** 测试foreach循环 */
        long ayyaybefore = System.currentTimeMillis();
        for(String ii : arrayList){
        }
        long ayyayafter = System.currentTimeMillis();
        System.out.println("arraylist使用foreach遍历的时间是:"+(ayyayafter-ayyaybefore)+"ms");

        ayyaybefore = System.currentTimeMillis();
        for(String ii : linkedList){
        }
        ayyayafter = System.currentTimeMillis();
        System.out.println("linkedlist使用foreach遍历的时间是:"+(ayyayafter-ayyaybefore)+"ms");

/** 测试 iterator 循环 */
        Iterator aiterator = arrayList.iterator();
        ayyaybefore = System.currentTimeMillis();
        while (aiterator.hasNext()){
            aiterator.next();
        }
        ayyayafter = System.currentTimeMillis();
        System.out.println("arraylist使用iterator遍历的时间是:"+(ayyayafter-ayyaybefore)+"ms");

        Iterator literator = linkedList.iterator();
        ayyaybefore = System.currentTimeMillis();
        while (literator.hasNext()){
            literator.next();
        }
        ayyayafter = System.currentTimeMillis();
        System.out.println("linkedList使用iterator遍历的时间是:"+(ayyayafter-ayyaybefore)+"ms");

/** 测试for循环 */
        ayyaybefore = System.currentTimeMillis();
        for(int ii=0; ii<arrayList.size(); ii++){
            arrayList.get(ii);
        }
        ayyayafter = System.currentTimeMillis();
        System.out.println("arrayList使用for遍历的时间是:"+(ayyayafter-ayyaybefore)+"ms");

        ayyaybefore = System.currentTimeMillis();
        for(int ii=0; ii<linkedList.size(); ii++){
            linkedList.get(ii);
        }
        ayyayafter = System.currentTimeMillis();
        System.out.println("linkedlist使用for遍历的时间是:"+(ayyayafter-ayyaybefore)+"ms");
    }

在这里插入图片描述

原因分析:
为什么LinkedList的for循环迭代这么慢呢?

我们先来看看LinkedList的get(int i)做了什么:

//get函数主要调用了node()函数
Node<E> node(int 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;
    }
}

由于LinkedList是双向链表,因此下面代码

 if (index < (size >> 1)) {

的意思是算出i在前一半还是后一半,一半前正序遍历、一半后倒序遍历,这样会快很多,当然,先不管这个,分析一下为什么使用普通for循环遍历LinkedList会这么慢。

原因就在两个for循环里面,以前者为例:
1、get(0),直接拿到0位的Node0的地址,拿到Node0里面的数据

2、get(1),直接拿到0位的Node0的地址,从0位的Node0中找到下一个1位的Node1的地址,找到Node1,拿到Node1里面的数据

3、get(2),直接拿到0位的Node0的地址,从0位的Node0中找到下一个1位的Node1的地址,找到Node1,从1位的Node1中找到下一个2位的Node2的地址,找到Node2,拿到Node2里面的数据。

后面的以此类推。也就是说,LinkedList在get任何一个位置的数据的时候,都会把前面的数据走一遍。

原文链接:加载失败,请重新获取