你可以通过这篇文章获得一些集合遍历的技巧。
Java有两种方法来遍历集合。一种是最基本的for-loop,另一种是由jdk5引入的for-each。通过这种方法,我们可以更方便地遍历数组和集合。但是你有没有想过这两种方法呢?哪种方法对遍历集合的效率更高?
for-each的实现原理
Foreach 不是一个新的语法,而是Java的一个语法糖。在编译时,编译器会将这段代码转换为迭代器的实现,并将其编译为字节码。我们可以通过执行命令javap -verbose Testforeach来反编译以下的编译代码
得到的详细字节码如下。
这个字节码的一般含义是使用getfield命令获得变量整数,并调用List.iterator获得 迭代器实例和调用iterator.hasNext。如果它返回真,则调用iterator.next方法。看,这就是迭代器遍历集合的实现逻辑。
基准测试
现在让我们使用for-loop方法和for-each方法来测试。
下面是测试结果。
正如你所看到的,结果很明显。对于ArrayList,使用for-loop方法的性能要比for-each方法的性能好。我们可以宣布for-loop获胜吗?答案是否定的。在下一个基准测试中,我们把ArrayList改为LinkedList。
同样,这里是测试结果。
原因分析
一些初学者可能会问,为什么 ArrayList使用for循环方法遍历得比较快,而LinkedList 比较慢,非常慢?这是由ArrayList和LinkedList的数据结构决定的。
ArrayList底层使用数组来存储元素。阵列是连续的内存空间。可以通过索引获得数据。时间复杂度是O(1),所以它很快速。
LinkedList的底层是一个双向的链接列表。使用for-loop来实现遍历,每次都需要从链表的头部节点开始。其时间复杂度为O(n*n)。
结论
- 使用ArrayList时,for-loop方法更快,因为for-each是由迭代器实现的,它需要进行并发的修改验证。
- 当使用LinkedList时,for-each要比for-loop快得多,因为LinkedList是通过使用双向链表实现的。每个寻址都需要从头节点开始。如果我们需要遍历LinkedList,我们需要避免使用for-loop。
- 使用迭代器模式,for-each不需要关心集合的具体实现。如果需要替换集合,不需要修改代码就可以轻松替换。
最后,感谢您的阅读,并期待您关注和阅读更多有趣的文章。
Java中的For Loop和Foreach哪个更快》最初发表于Medium上的Javarevisited,人们在这里通过强调和回应这个故事来继续对话。