传统for循环与Java中的Iterator / foreach的性能

在遍历ArrayList,HashMap和其他集合时比较传统的for循环与Iterator是否有任何性能测试结果可用?

或者干脆为什么我应该使用Iterator over循环,反之亦然?


假设这是你的意思:

// 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),迭代器速度更快。 对于数组和ArrayLists,性能差异应该可以忽略不计。

编辑:我相信微观基准是非常邪恶的根源,就像早期的优化一样。 但是,我认为,对于这些相当琐碎的事情的影响感觉很好。 因此我运行了一个小测试:

  • 迭代遍历LinkedList和ArrayList
  • 带有100,000个“随机”字符串
  • 总结它们的长度(只是为了避免编译器优化整个循环)
  • 使用所有3个循环样式(迭代器,每个循环都有一个计数器)
  • 结果对于所有人来说都是相似的,但是对于使用LinkedList的“with with counter”。 所有其他五个都花了不到20毫秒来遍历整个列表。 在LinkedList上使用list.get(i) 100,000次完成超过2分钟(!)(慢60,000次)。 哇! :)因此,最好使用迭代器(明确或隐含地为每个迭代器使用),特别是如果您不知道处理的列表的类型和大小。


    使用迭代器的第一个理由显然是正确的。 如果您使用手动索引,则可能会出现非常无害的逐个错误,只有仔细观察才能看到:您是从1还是从0开始? 你有没有完成length - 1 ? 你使用<<= ? 如果您使用迭代器,则更容易发现它实际上迭代了整个数组。 “说出你的所作所为,按照你的意思行事。”

    第二个原因是统一访问不同的数据结构。 一个数组可以通过索引有效地访问,但是链接列表最好通过记住最后访问的元素来遍历(否则你会得到一个“Shlemiel画家”)。 哈希映射更加复杂。 通过提供来自这些数据结构和其他数据结构的统一接口(例如,您也可以进行树遍历),您将再次获得明显的正确性。 遍历逻辑必须仅实现一次,而使用它的代码可以简洁地“说出它做了什么,然后做它说的。”


    性能在大多数情况下是相似的。

    但是,每当一个代码收到一个List,并在其上循环时,就有一个众所周知的情况:
    对于所有不实现RandomAccess的List实现 (例如:LinkedList) ,Iterator更好

    原因在于对于这些列表,按索引访问元素不是一个常量时间操作。

    所以你也可以认为迭代器更加健壮(实现细节)。


    一如既往,性能不应该成为隐藏可读性问题。
    java5的foreach循环在这方面很受欢迎:-)

    链接地址: http://www.djcxy.com/p/52985.html

    上一篇: Performance of traditional for loop vs Iterator/foreach in Java

    下一篇: How does the Java 'for each' loop work?