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

1sbrub3j  于 2021-07-03  发布在  Java
关注(0)|答案(6)|浏览(364)

这个问题在这里已经有答案了

for循环和for-each循环之间是否存在性能差异((16个答案)
三年前关门了。
在java中,以传统的方式迭代数组是否更快,

for (int i = 0; i < a.length; i++)
    f(a[i]);

或者用更简洁的形式,

for (Foo foo : a)
    f(foo);

对于arraylist,答案是否相同?
当然,对于大量的应用程序代码来说,答案是它没有明显的区别,因此为了可读性,应该使用更简洁的形式。然而,我所看到的环境是繁重的技术计算,操作必须执行数十亿次,所以即使是微小的速度差异最终也可能是显著的。

monwx1rj

monwx1rj1#

如果你在一个数组中循环,那就没关系了——增强的for循环使用数组访问。
例如,考虑以下代码:

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

当用反编译时 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

现在将其更改为使用显式数组访问:

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

这将反编译为:

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

在增强的for循环中有更多的设置代码,但它们基本上是做同样的事情。不涉及迭代器。此外,我还希望它们能够被jitted到更相似的代码。
建议:如果您真的认为它可能会有显著的不同(只有在循环体非常小的情况下才会如此),那么您应该用实际应用程序对其进行基准测试。这是唯一重要的情况。

col17t5w

col17t5w2#

对于linkedlist:

for(ClassOfElement element : listOfElements) {
  System.out.println(element.getValue());
}

之前有人回答:
for循环和for-each循环之间是否存在性能差异?

yk9xbfzb

yk9xbfzb3#

这完全属于微观优化领域。真的没关系。从风格上来说,我总是更喜欢第二种,因为它更简洁,除非你需要循环计数器来做其他事情。这远比这种微观优化更重要:可读性。
也就是说,对于arraylist来说没有太大的区别,但是linkedlist会比第二个更有效。

n1bvdmb6

n1bvdmb64#

测量一下。所有性能问题的答案都取决于虚拟机版本、处理器、内存速度、缓存等,因此您必须针对特定的平台进行度量。
就我个人而言,我更喜欢第二种变体,因为其意图更为明确。如果性能成为一个问题,我可以优化它以后无论如何-如果代码真的是对整个应用程序的性能很重要。

xt0899hw

xt0899hw5#

在数组或randomaccess集合中,您可以通过执行以下操作来略微提高速度:

List<Object> list = new ArrayList<Object>();

for (int i=0, d=list.size(); i<d; i++) {
    something(list.get(i));
}

但我一般不会担心。像这样的优化对代码的影响不会超过0.1%。试着用-prof调用java来查看代码实际花费的时间。

wko9yo5t

wko9yo5t6#

更快的方法是使用fork-join框架的parallelarray(如果您有足够大的数据集)。

相关问题