关于for循环和Iterator遍历ArrayList的性能问题

今日看到@DriveMan的一篇博客,题为《ArrayList集合实现RandomAccess接口有何作用?为何LinkedList集合却没实现这接口?》,文中提到对于实现了RandomAccess接口的类来说,使用for循环遍历比使用Iterator遍历更加高效快速。

由于本人之前没了解过这方面的知识,阅此博客后心怀好奇便去查阅了API文档了解了一下,官网的介绍是这样的:

Marker interface used by List implementations to indicate that they support fast (generally constant time) random access. The primary purpose of this interface is to allow generic algorithms to alter their behavior to provide good performance when applied to either random or sequential access lists.

 上面这段话的意思就是:RandomAccess是一个标记接口,用于标明实现了该接口的List支持快速随机访问。并且指出了该接口的主要用途是当随机或顺序访问一些List时,允许泛型算法改变它们的行为来提升性能。

此外,官方还列举了一个例子,提到使用for循环遍历的速度会比Iterator遍历的速度要快。原文如下:

     for (int i=0, n=list.size(); i < n; i++)
         list.get(i);

runs faster than this loop:
     
     for (Iterator i=list.iterator(); i.hasNext(); )
         i.next();

在@DriveMan的文中,测试了for与Iterator遍历ArrayList的性能,结论与官网描述一致,for循环稍快与Iterator。


怀着一颗好奇心,本人也想试试看是否真的如此,于是也开始了测试。话不多说,直接上代码和结果:

public class ArrayListDemo {
    public static void main(String[] args) {
        //存储一些数据到集合中
        List<Integer> arrayList = new ArrayList<>();
        for (int i = 0; i < 50000; i++) {
            arrayList.add(i);
        }
        System.out.println("for遍历ArrayList:" + arrayListFor(arrayList));
        System.out.println("Iterator遍历ArrayList:" + arrayListIterator(arrayList));
    }
    //使用for循环遍历ArrayList
    public static long arrayListFor(List<Integer> arrayList) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < arrayList.size(); i++) {
            arrayList.get(i);
        }
        long end = System.currentTimeMillis();
        return end - start;
    }
    //使用Iterator遍历ArrayList
    public static long arrayListIterator(List<Integer> arrayList) {
        long start = System.currentTimeMillis();
        for (Iterator i = arrayList.iterator(); i.hasNext();) {
            i.next();
        }
        long end = System.currentTimeMillis();
        return end - start;
    }
}

首先我准备了50000条数据进行测试,这与@DriveMan文中是一致的,这样方便对比。运行5次后,结果如下:

50000条数据时的测试结果
遍历方式第1次运行第2次运行第3次运行第4次运行第5次运行
for5 ms3 ms4 ms5 ms4 ms
Iterator5 ms4 ms5 ms5 ms3 ms

由以上结果可以看到,50000条数据时,for循环略占优一些(但第5次运行是Iterator占优)。


由于数据量过少,for优势好像不是很明显,于是我将数据量改为50000000,再次测试for与Iterator的性能并进行对比,测试结果如下:

50000000条数据时的测试结果
遍历方式第1次运行第2次运行第3次运行第4次运行第5次运行
for52 ms47 ms56 ms50 ms45 ms
Iterator15 ms12 ms11 ms15 ms11 ms

奇怪的现象出现了!50000000条数据时,for遍历耗费的时间基本都是Iterator的4倍左右!for循环遍历完全落入下风!

反复测试之,依旧如此,这似乎与官网API文档中的描述矛盾了。

至此,原因未知,如有知情者,欢迎在下方评论解释一下,指导指导大家。

如本文中有错误,恳请指出,感激不尽。

欢迎大家加入自学Java的QQ群25011579,里面全都是自学Java的小伙伴,大家一起努力吧!

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值