美文网首页
集合遍历那些事儿-foreach & for

集合遍历那些事儿-foreach & for

作者: Bardon_X | 来源:发表于2019-03-07 11:58 被阅读0次

    一般情况下,我们知道ArrayList底层结构是数组,而LinkedList底层结构是链表。ArrayList查询快插入删除慢,LinkedList查询慢插入删除快。那么当涉及到遍历呢?使用何种方式的遍历会更快呢?

    这里参考Williamwhc大哥的博文,我验证了一下  foreach与for的效率对比

    这里为看起来简洁使用了图片,想拷代码的可以点击上面链接过去。


    以上两种方式分别通过foreach 和 for的方式进行对比。当我把容量设置成十万的时候:


    当我把容量设置成1百万的时候:


    原谅我不厚道地笑了,当数据达到1百万时,LinkedList要等很久(注意上图,我换了一下方法顺序,不然阻塞住了)。

    于是学着大哥看了看编译后的指令(使用win时,出现了乱码,将win编码设置成utf-8就行了,即 chcp 65001,顺便说一下设置成GBK是chcp 936,设置英语是chcp 437):

    首先编译 javac -verbose x.java 可以看到虚拟机编译是做了些什么?

    编译成字节码文件,查看一下指令 javap -c ForTest

    可以观察得到:for循环,是调用get(index)方法,而foreach是使用迭代器的方式。

    再看看迭代器的实现:

    先看看ArrayList 和 LinkedList继承体系:

    都有一个最初实现接口:Iterable,再看看他们分别如何实现Iterable接口

    ArrayList LinkedList

    看,熟悉的数组、链表遍历操作!

    总结:

    ①增强for循环(即foreach)其实是使用了迭代器的方式遍历集合。②ArrayList,底层是数组结构,for和foreach效率上并不是差太多,都是使用get(index)方式迭代,即物理地址+偏移量直接获取绝对地址,访问很快。③LinkedList,底层是链表结构,for和foreach效率差距十分明显。for循环使用get(index)其实是要从头开始遍历,这也是为什么当数据级别到1百万时,所花费的时间不是线性关系(都没有耐性等待结果了);foreach循环其实就是调用next()方法从前一个节点移到下一个节点。

    猜想:

    原则上,是不是我们自己定义一个集合,实现了Iterable,当使用foreach遍历时,JIT也会在字节码层面翻译成调用Iterable的方法呢?

    相关文章

      网友评论

          本文标题:集合遍历那些事儿-foreach & for

          本文链接:https://www.haomeiwen.com/subject/hvwqpqtx.html