JAVA集合:for循环、foreach、迭代器效率比较

前言

写代码的过程中,经常需要遍历集合,选择一个高效的遍历方法非常重要,今天来看下for循环、foreach、迭代器效率比较,主要从ArrayList和LinkedList来分析。
直接上代码测试

ArrayList


        List<Integer> integers = Lists.newArrayList();
        for(int i=0;i<100000;i++){
            integers.add(i);
        }

        long start1 = System.currentTimeMillis();
        for(int count =0 ;count<10;count++){
            for(int i=0;i<integers.size();i++){
                int j=integers.get(i);
            }
        }
        System.out.println(String.format("for循环100次时间:%s ms",System.currentTimeMillis()-start1));

        long start2 = System.currentTimeMillis();
        for(int count =0 ;count<10;count++) {
            for (Integer i : integers) {
               int j = i;
            }
        }
        System.out.println(String.format("foreach循环100次时间:%s ms",System.currentTimeMillis()-start2));

        long start3 = System.currentTimeMillis();
        for(int count =0 ;count<10;count++) {
            Iterator<Integer> iterator = integers.iterator();
            while(iterator.hasNext()){
                int j=iterator.next();
            }
        }
        System.out.println(String.format("迭代器循环100次时间:%s ms",System.currentTimeMillis()-start3));

结果:

for循环100次时间:15 ms
foreach循环100次时间:25 ms
迭代器循环100次时间:20 ms

ArrayList下三者效率差不多,for循环最优,因为ArrayList通过数组来实现,数组通过索引来定位的时间复杂度是O(1),1次就能定位到,所以效率非常高

LinkedList

List<Integer> integers = Lists.newLinkedList();
        for(int i=0;i<100000;i++){
            integers.add(i);
        }

        long start1 = System.currentTimeMillis();
        for(int count =0 ;count<10;count++){
            for(int i=0;i<integers.size();i++){
                int j=integers.get(i);
            }
        }
        System.out.println(String.format("for循环100次时间:%s ms",System.currentTimeMillis()-start1));

        long start2 = System.currentTimeMillis();
        for(int count =0 ;count<10;count++) {
            for (Integer i : integers) {
               int j = i;
            }
        }
        System.out.println(String.format("foreach循环100次时间:%s ms",System.currentTimeMillis()-start2));

        long start3 = System.currentTimeMillis();
        for(int count =0 ;count<10;count++) {
            Iterator<Integer> iterator = integers.iterator();
            while(iterator.hasNext()){
                int j=iterator.next();
            }
        }
        System.out.println(String.format("迭代器循环100次时间:%s ms",System.currentTimeMillis()-start3));

结果:

for循环100次时间:59729 ms
foreach循环100次时间:18 ms
迭代器循环100次时间:14 ms

可以看到for循环在LinkedList下效率特别低,我们来看下LinkedList的get做了什么

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

get调用到node(index)方法,从代码可以看到,当index<size/2时从前往后找,否则从后往前找,使LinkedList的每个元素通过下标方式查找最多查询size/2次,因此遍历100000个元素总共需要查询的次数是size/2/2size = 100000100000/4,效率远低于ArrayList通过下标直接定位,总共只需要查询100000次,所以经常会说LinkedList的查询效率低,ArrayList的查询效率高,其实这里指的是for循环通过下标查找的角度,通过迭代器查找的效率都很高,差不多。

猜你喜欢

转载自blog.csdn.net/qq_28605513/article/details/84981338