Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中传统for循环与迭代器/foreach的性能比较_Java_Map_Iterator_Arraylist_For Loop - Fatal编程技术网

Java中传统for循环与迭代器/foreach的性能比较

Java中传统for循环与迭代器/foreach的性能比较,java,map,iterator,arraylist,for-loop,Java,Map,Iterator,Arraylist,For Loop,在遍历ArrayList、HashMap和其他集合时,比较传统的for循环和迭代器是否有性能测试结果 或者简单地说,为什么我应该在循环中使用迭代器,或者反过来使用迭代器?在生成的代码中使用或,您将看到没有真正的区别。新迭代器形式的优点是它在代码库中看起来更干净 编辑:我从其他答案中看到,您实际上指的是使用get(I)与迭代器之间的区别。我把最初的问题理解为使用迭代器的新旧方法之间的区别 使用get(i)并维护自己的计数器,特别是对于列表类,这不是一个好主意,原因在公认的答案中提到。假设这就是您的

在遍历ArrayList、HashMap和其他集合时,比较传统的for循环和迭代器是否有性能测试结果

或者简单地说,为什么我应该在循环中使用迭代器,或者反过来使用迭代器?

在生成的代码中使用或,您将看到没有真正的区别。新迭代器形式的优点是它在代码库中看起来更干净

编辑:我从其他答案中看到,您实际上指的是使用get(I)与迭代器之间的区别。我把最初的问题理解为使用迭代器的新旧方法之间的区别


使用get(i)并维护自己的计数器,特别是对于
列表
类,这不是一个好主意,原因在公认的答案中提到。

假设这就是您的意思:

// 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
}
//传统for循环
对于(int i=0;i
迭代器对于无随机访问的集合(例如TreeSet、HashMap、LinkedList)更快。对于数组和ArrayList,性能差异应该可以忽略不计

编辑:我相信微观基准测试是非常邪恶的根源,就像早期优化一样。但是,再一次,我认为对这些非常琐碎的事情的含义有一种感觉是很好的。因此我跑:

  • 分别迭代LinkedList和ArrayList
  • 有100000个“随机”字符串
  • 总结它们的长度(避免编译器优化整个循环)
  • 使用所有3种循环样式(迭代器、每个循环、带计数器循环)

除了使用LinkedList的“for with counter”外,其他所有的结果都类似。所有其他五个都用了不到20毫秒的时间遍历整个列表。在LinkedList上使用
list.get(i)
100000次需要2分钟以上(!)才能完成(慢60000倍)。哇!:)因此,最好使用迭代器(显式或隐式地使用for each),特别是当您不知道要处理的列表的类型和大小时

在大多数情况下,性能相似

但是,每当代码接收到列表并在其上循环时,就会出现一种众所周知的情况:
迭代器对于所有不实现随机访问的列表实现来说都要好得多(例如:LinkedList)

原因是对于这些列表,通过索引访问元素不是一个固定的时间操作

<>您也可以将迭代器视为更健壮(对实现细节)。


与往常一样,性能不应被忽略,因为它隐藏了可读性问题。

java5foreach循环在这方面非常成功:-)

在i++语法上使用迭代器的最佳原因之一是,并非所有数据结构都支持随机访问,更不用说它的性能了。您还应该对列表或集合接口进行编程,这样,如果您以后决定另一个数据结构将更有效,您就可以在不进行大规模手术的情况下将其交换出去。在这种情况下(对接口进行编码的情况),您不一定知道实现细节,而将其推迟到数据结构本身可能更明智

我学会坚持使用for-each的原因之一是它简化了嵌套循环,尤其是在2+维循环上。所有的i、j和k都可能会很快变得混乱。

使用迭代器的第一个原因是明显的正确性。如果您使用手动索引,可能会出现一些非常无害的off-by-one错误,只有仔细观察才能看到这些错误:您是从1开始还是从0开始?你是以
长度-1完成的吗?你有没有用
+1来解释Sfussengerger所说的。仅供参考,无论您使用显式迭代器还是隐式迭代器(即针对每个迭代器),都不会产生性能差异,因为它们编译为相同的字节码

我不相信

for (T obj : collection) {
每次通过循环计算.size(),因此比

for (int i = 0; i < collection.size(); i++) {
for(int i=0;i
是的,它确实会对不是基于随机访问的集合(如LinkedList)产生影响。内部的链表由指向下一个的节点(从头节点开始)实现

链表中的get(i)方法从head节点开始,通过链接一直导航到第i个节点。当您使用传统的for循环在链表上迭代时,每次都从head节点开始,因此整体遍历变成二次遍历

for( int i = 0; i< list.size(); i++ ) {
    list.get(i); //this starts everytime from the head node instead of previous node
}

谢谢,但是ArrayList呢?ArrayList实现了随机访问,因此list.get(i)是快速的。性能差异应该可以忽略不计。注意:虽然我不知道JDK中的LinkedList是否是以这种方式编写的,但是编写一个LinkedList实现,其中传统的for循环的执行速度与随机访问的速度一样快,这将是微不足道的。所需要的只是保留一个指向最后一个el的内部指针请求随机访问的元素。这似乎是一个微不足道的实现,它会加速许多代码,我无法想象它不在其中。@tster:实际上迭代器就是这样做的。你的LinkedList结果显示了当你从O(n)到O(n^2)(或更多)时会发生什么所有其他五个在整个列表上迭代不到20毫秒的时间看起来像是JVM死代码优化开始了…LinkedList和ArrayList的迭代之间的差异是显著的(有利于ArrayList)@bestsss不,它当然没有。我已经生成了100000个随机字符串(实际上是UUID)把它们的长度加起来就是p
for( Object item: list ) {
    //item element is obtained from the iterator's next method.
}