Java循环效率(“for”与“foreach”)

(对于那些熟悉JVM编译和优化技巧的人来说一个问题…… 🙂

是否有任何“for”和“foreach”模式明显优于其他模式?

考虑以下两个例子:

public void forLoop(String[] text) { if (text != null) { for (int i=0; i<text.length; i++) { // Do something with text[i] } } } public void foreachLoop(String[] text) { if (text != null) { for (String s : text) { // Do something with s, exactly as with text[i] } } } 

forLoopforeachLoop更快还是更慢?

假设在这两种情况下, text数组都不需要进行任何健全性检查,是否有明显的赢家或者仍然太靠近而不能打电话?

编辑:正如在一些答案中所指出的,对于数组,性能应该是相同的,而对于像List这样的抽象数据类型,“foreach”模式可能稍微好一些。 另请参阅讨论该主题的答案 。

从JLS第14.14.2节 :

否则,Expression必须具有数组类型T []。 设L1 … Lm是紧接在增强for语句之前的(可能是空的)标签序列。 然后,增强的for语句的含义由以下基本语句给出:

 T[] a = Expression; L1: L2: ... Lm: for (int i = 0; i < a.length; i++) { VariableModifiersopt Type Identifier = a[i]; Statement } 

换句话说,我希望它们最终被编译成相同的代码。

肯定有一个明显的赢家:增强的for循环更具可读性 。 这应该是你最关心的问题 - 当你certificate最可读的forms没有你想要的那么好时,你甚至应该考虑微观优化这种事情。

您可以编写自己的简单测试,以测量执行时间。

 long start = System.currentTimeMillis(); forLoop(text); long end = System.currentTimeMillis(); long result = end - start; 

结果是执行时间。

除非您知道性能问题,否则您应该选择几乎每次都更具可读性的选项。

在这种情况下,我会说他们保证是一样的。

唯一的区别是你额外检查text.length可能会更慢,而不是更快。

我还要确保文本永远不会静态。 例如,使用@NotNull注释。 最好在编译/构建时捕获这些问题(并且会更快)

由于您使用的是array类型,性能差异无关紧要。 在完成optimization漏斗后,他们最终会提供相同的性能。

但是如果你使用像List这样的ADT,那么与多个get(i)调用相比, forEachLoop显然是最好的选择。

即使对于数组,使用for-each循环也没有性能损失。 事实上,在某些情况下,它可能比普通的for循环提供轻微的性能优势,因为它只计算一次数组索引的限制。 详情请点击这篇文章 。