ArrayList容器三种遍历元素方法的性能对比报告

上周有同事问我ArrayList容器中for循环、ForEach循环和iterator迭代哪种性能更好。其实在此之前我是没有测试过的,所以我想当然地认为,既然iterator方式需要先获取一个iterator,性能应该要差一些。

没有验证过的结论,如鲠在喉。

终于我还是写了下面这个小程序,来验证我的想法。

结果大出我的意料之外。

从上面的测试结果来看,for方式几乎是iterator方式的3倍,而iterator方式几乎是foreach的1.5倍!

秉着探究事实真相的精神,我们来分析下这到底是怎么一回事。

先来看foreach和iterator的差异性。下面是使用javap命令把java的字节码反编译后的Java虚拟机规范定义的字节代码指令,我们来对比下它们的差异性。


ForEach方式:



Iterator方式:



可以看出,foreach循环竟然是用iterator实现的,除了高亮标注的第4、5行外,其它的指令和显式使用iterator方式一模一样。令人不解的是,foreach循环竟然还比显式使用iterator的方式多出了两条指令。看来这就是foreach循环比iterator迭代慢的原因了。jdk5引入的这一新特性除了让代码看起来简洁外,并没有什么高明之处。有点小失望。
再来看看for循环的字节代码指令:



foreach和iterator方式的循环体中有两条invokeinterface的指令;而for循环中只有一条invokeinterface指令,其余的都是堆栈操作,而堆栈操作是快于invokeinterface操作的。这也是for循环快于iterator的原因。
这么看来,要遍历ArrayList中的元素,还是首推for循环,好处有两点:

  1. 速度快
  2. 有的情况下你是需要一个索引号的,而for循环默认就提供了,iterator和foreach还得额外定义变量。

当然,上面的例子中for循环快于iterator是有条件限制的。还是拿上述例子来说,for循环中调用的是list.get方法,而该list是ArrayList,get方法其实就是根据数字下标获取对象。ArrayList的读取是非常快的,就那么几条汇编指令,时间复杂度是o(1)。但是如果把ArrayList换成LinkedList,for循环就会比iterator慢上2 ~ 3个数量级了。原因就在于linkedlist的get方法调用每次都要遍历一遍LinkedList,时间复杂度是o(n)。当然,罪魁祸首是LinkedList.get方法。我贴一个测试结果给你看就明白了。

因此,如果要遍历LinkedList容器中的元素,最好还是显式的使用iterator方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值