Java 中传统 for 循环与迭代器/foreach 的性能
在遍历 ArrayList、HashMap 和其他集合时,在比较传统的 for 循环与迭代器时,是否有任何性能测试结果?
或者简单地说,为什么我应该使用迭代器 over for loop,反之亦然?
在遍历 ArrayList、HashMap 和其他集合时,在比较传统的 for 循环与迭代器时,是否有任何性能测试结果?
或者简单地说,为什么我应该使用迭代器 over for loop,反之亦然?
假设这是你的意思:
// traditional for loop
for (int i = 0; i < collection.size(); i++) {
T obj = collection.get(i);
// snip
}
// using iterator
Iterator<T> iter = collection.iterator();
while (iter.hasNext()) {
T obj = iter.next();
// snip
}
// using iterator internally (confirm it yourself using javap -c)
for (T obj : collection) {
// snip
}
对于没有随机访问的集合(例如TreeSet,HashMap,LinkedList),迭代器更快。对于数组和数组列表,性能差异应该可以忽略不计。
编辑:我相信微基准测试是邪恶的根源,就像早期优化一样。但话又说回来,我认为对这种非常微不足道的事情的影响有一种感觉是件好事。因此,我运行了一个小测试:
除了LinkedList的“for with counter”之外,所有结果都是相似的。所有其他五个都花了不到20毫秒的时间来迭代整个列表。在LinkedList上使用100,000次需要超过2分钟(!)才能完成(慢60,000倍)。哇!:)因此,最好使用迭代器(显式或隐式地用于每个迭代器),特别是如果您不知道要处理的列表的类型和大小。list.get(i)
使用迭代器的第一个原因是明显的正确性。如果您使用手动索引,则可能存在非常无害的偏离一个错误,只有仔细观察才能看到这些错误:您是从1开始还是从0开始?你完成了吗?您是否使用 或 ?如果使用迭代器,则更容易看出它确实在迭代整个数组。“说你做什么,做你说的。length - 1
<
<=
第二个原因是对不同数据结构的统一访问。数组可以通过索引有效地访问,但最好通过记住最后访问的元素来遍历链表(否则你会得到一个“画家什勒米尔”)。哈希映射甚至更复杂。通过从这些和其他数据结构提供统一的接口(例如,您还可以进行树遍历),您可以再次获得明显的正确性。遍历逻辑只需要实现一次,使用它的代码可以简洁地“说出它所做的事情,并按照它所说的去做”。