在Java中迭代数组的最快方法:循环变量vs增强语句

rwa*_*ace 28 java iteration performance

在Java中,以老式的方式迭代数组是否更快,

for (int i = 0; i < a.length; i++)
    f(a[i]);
Run Code Online (Sandbox Code Playgroud)

或者使用更简洁的表格,

for (Foo foo : a)
    f(foo);
Run Code Online (Sandbox Code Playgroud)

对于ArrayList,答案是否相同?

当然,对于大量的应用程序代码,答案是它没有明显的区别,因此应该使用更简洁的表单来提高可读性.然而,我正在研究的背景是重型技术计算,必须执行数十亿次操作,因此即使很小的速度差异也可能最终显着.

Jon*_*eet 55

如果你在数组中循环,那应该没关系 - 增强的for循环无论如何都使用了数组访问.

例如,考虑以下代码:

public static void main(String[] args)
{
    for (String x : args)
    {
        System.out.println(x);
    }
}
Run Code Online (Sandbox Code Playgroud)

javap -c Test我们得到反编译时(对于main方法):

public static void main(java.lang.String[]);
  Code:
   0:   aload_0
   1:   astore_1
   2:   aload_1
   3:   arraylength
   4:   istore_2
   5:   iconst_0
   6:   istore_3
   7:   iload_3
   8:   iload_2
   9:   if_icmpge   31
   12:  aload_1
   13:  iload_3
   14:  aaload
   15:  astore  4
   17:  getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   20:  aload   4
   22:  invokevirtual   #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   25:  iinc    3, 1
   28:  goto    7
   31:  return
Run Code Online (Sandbox Code Playgroud)

现在更改它以使用显式数组访问:

public static void main(String[] args)
{
    for (int i = 0; i < args.length; i++)
    {
        System.out.println(args[i]);
    }
}
Run Code Online (Sandbox Code Playgroud)

这反编译为:

public static void main(java.lang.String[]);
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   aload_0
   4:   arraylength
   5:   if_icmpge   23
   8:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   11:  aload_0
   12:  iload_1
   13:  aaload
   14:  invokevirtual   #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   17:  iinc    1, 1
   20:  goto    2
   23:  return
Run Code Online (Sandbox Code Playgroud)

在增强的for循环中有更多的设置代码,但它们基本上做同样的事情.没有涉及迭代器.此外,我希望他们能够获得更多相似代码的JIT.

建议:如果你真的认为它可能使一个显著差异(这只会永远做,如果循环体是绝对微乎其微),那么你应该基准它与您的实际应用.这是唯一重要的情况.


cle*_*tus 22

这完全属于微优化领域.这没关系.从文体上来说,我总是喜欢第二种,因为它更简洁,除非你需要循环计数器来做其他事情.这比这种微优化更重要:可读性.

话虽这么说,对于一个ArrayList,没有太大的区别,但是第二个是LinkedList会更有效率.

  • 它不会为数组使用迭代器. (5认同)
  • 第二种也是受限制的,因为数组具有最大的Integer.MAX_VALUE数量的元素,并且ArrayList由数组支持. (2认同)

Mne*_*nth 7

测量它.所有性能问题的答案可能取决于VM版本,处理器,内存速度,缓存等.因此,您必须针对您的特定平台进行测量.

我个人更喜欢第二种变体,因为意图更清晰.如果性能成为一个问题,我可以在以后优化它 - 如果该代码对整个应用程序的性能非常重要.