for 循环和 for-each 循环之间是否存在性能差异?
以下两个循环之间的性能差异(如果有)是什么?
for (Object o: objectArrayList) {
o.DoSomething();
}
和
for (int i=0; i<objectArrayList.size(); i++) {
objectArrayList.get(i).DoSomething();
}
以下两个循环之间的性能差异(如果有)是什么?
for (Object o: objectArrayList) {
o.DoSomething();
}
和
for (int i=0; i<objectArrayList.size(); i++) {
objectArrayList.get(i).DoSomething();
}
摘自Joshua Bloch在《Effective Java》中的第46项:
在 1.5 版中引入的 for-each 循环通过完全隐藏迭代器或索引变量来消除混乱和出错的机会。生成的成语同样适用于集合和数组:
// The preferred idiom for iterating over collections and arrays for (Element e : elements) { doSomething(e); }
当您看到冒号(:)时,请将其读作“in”。因此,上面的循环读作“对于元素中的每个元素 e”。请注意,使用 for-each 循环不会降低性能,即使对于数组也是如此。实际上,在某些情况下,与普通的 for 循环相比,它可能会提供轻微的性能优势,因为它只计算数组索引的限制一次。虽然你可以手动完成此操作(项目45),但程序员并不总是这样做。
所有这些循环都完全相同,我只想在投入两美分之前展示这些循环。
首先,循环访问 List 的经典方式:
for (int i=0; i < strings.size(); i++) { /* do something using strings.get(i) */ }
其次,首选方式,因为它不容易出错(你做过多少次“哎呀,在循环中的这些循环中混合变量i和j”的事情?
for (String s : strings) { /* do something using s */ }
三、微优化循环:
int size = strings.size();
for (int i = -1; ++i < size;) { /* do something using strings.get(i) */ }
现在实际的两分钱:至少在我测试这些时,第三个是最快的,当计算每种类型的循环所花费的时间的毫秒时,其中的简单操作重复了几百万次 - 这是在Windows上使用Java 5和jre1.6u10,以防有人感兴趣。
虽然它至少看起来是第三个最快的,但你真的应该问问自己,你是否想冒险在你的循环代码中到处实现这种窥视孔优化,因为从我所看到的,实际的循环通常不是任何真实程序中最耗时的部分(或者也许我只是在错误的领域工作, 谁知道)。而且,就像我在Java for-each循环的借口中提到的(有些人将其称为Iterator循环,而另一些人则将其称为for-in循环),在使用它时,您不太可能遇到一个特定的愚蠢错误。在讨论它如何比其他字节码更快之前,请记住javac根本不优化字节码(好吧,几乎根本没有),它只是编译它。
如果你喜欢微优化和/或者你的软件使用了很多递归循环,那么你可能对第三个循环类型感兴趣。只要记住在将for循环更改为这个奇怪的微优化循环之前和之后都要对软件进行良好的基准测试。