像这样在Java中遍历列表是否会更慢:
for (int i=0;i<list.size();i++) {
.. list.get(i)
}
相反:
for (Object o: list) {
... o
}
像这样在Java中遍历列表是否会更慢:
for (int i=0;i<list.size();i++) {
.. list.get(i)
}
相反:
for (Object o: list) {
... o
}
我认为你只是出于纯好奇心而提问,并不会引用 Knuth(可能有人会这么做)。
我认为,一旦你的代码被编译,就没有什么区别了。它在之前确实有所区别(例如示例2更易读更简洁),因此请使用第二个,不必担心其他问题。
仅供参考。
编辑
请注意,片段1中的代码每次循环运行时都会计算list.size()
,这可能比第2个示例还要慢。
另一个编辑
我需要再次确认一下,Joshua Bloch 建议使用for each
循环(请参阅Effective Java的第46项)。我相信这将结束所有讨论。感谢 Josh! :)
对于普通列表,性能不应该有任何明显的差异。
对于链表,迭代器将更快,特别是对于大型列表。
ArrayList
”。 - Stephen C for( Object o: list ) {
}
仅在您有充分证据表明使用它会导致性能问题时(例如,您对应用程序进行了剖析,并且发现代码的这一部分需要改进),才切换到前者。
如果不这样做,您可能无法在以后的重构中切换实现(因为您将被绑定到for( int i = 0 ; i < list.size(); i++ )
惯用语)。
可能会有所不同。
如果一个列表实现也实现了java.util.RandomAccess(例如ArrayList),那么使用它的get()方法比使用迭代器要快得多。
如果它没有实现java.util.RandomAccess(例如LinkedList),那么使用迭代器会更快。
然而,这只有在您使用包含数千个(可能分散的)对象或经常遍历的列表时才会有影响(就像对表示数值向量的List对象执行大量数学运算一样)。
每次迭代检查大小确实会增加i
个操作,但对性能影响不大。
我的意思是,这两种方法之间只有微小的差别。
int lsize = myList.size();
for(int i=0; i < lsize; i++)
{
Object o = myList.get(i);
}
对比:
for(int i=0; i < myList.size(); i++)
{
Object o = myList.get(i);
}
但实际上这并不重要。使用你问题中的第二个选项可以提高可读性,还有其他原因。
我自己没有深入研究所有列表实现中get()
的代码,所以我写的可能是一些虚假信息(FUD)。我学到的是,在for循环中使用get(i)
会导致每次循环都对整个列表进行迭代。而使用迭代器(就像增强型for循环一样)只会将迭代器移动到下一个列表元素,而不会再次对整个列表进行迭代。
我的结论是,使用迭代器或增强型for循环应该更高效,因为使用get()
会导致复杂度为O(n^2)
,而不是O(n)
。
我们认识到随机访问和顺序访问之间的区别常常模糊不清。例如,一些List实现在它们变得非常大时提供渐进线性的访问时间,但在实践中提供恒定的访问时间。这样的List实现通常应该实现此接口。作为一个经验法则,如果对于类的典型实例,以下循环:
for (int i=0, n=list.size(); i < n; i++) list.get(i);比以下循环运行得更快,则List实现应该实现此接口:
for (Iterator i=list.iterator(); i.hasNext(); ) i.next();