zoukankan      html  css  js  c++  java
  • 关于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次运行
    for 5 ms 3 ms 4 ms 5 ms 4 ms
    Iterator 5 ms 4 ms 5 ms 5 ms 3 ms
    由以上结果可以看到,50000条数据时,for循环略占优一些(但第5次运行是Iterator占优)。

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

    50000000条数据时的测试结果
    遍历方式 第1次运行 第2次运行 第3次运行 第4次运行 第5次运行
    for 52 ms 47 ms 56 ms 50 ms 45 ms
    Iterator 15 ms 12 ms 11 ms 15 ms 11 ms
    奇怪的现象出现了!50000000条数据时,for遍历耗费的时间基本都是Iterator的4倍左右!for循环遍历完全落入下风!

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

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

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

  • 相关阅读:
    123457123457#0#-----com.threeapp.renzhepaoku01----儿童跑酷游戏(忍者版)
    123456123456#0#-----com.threeapp.xiongMaoPaoPao01----熊猫跑酷01
    123456123456#0#-----com.threeapp.JiQiRenDaZhan01----机器人大战恐龙
    HashMap的工作原理
    Java 虚拟机
    分布式之缓存系统
    分库分表之后,id 主键如何处理?
    如何设计可以动态扩容缩容的分库分表方案?
    为什么要分库分表?用过哪些分库分表中间件?不同的分库分表中间件都有什么优点和缺点?
    如何实现 MySQL 的读写分离?MySQL 主从复制原理的是啥?如何解决 MySQL 主从同步的延时问题?
  • 原文地址:https://www.cnblogs.com/muhy/p/10593405.html
Copyright © 2011-2022 走看看