在Java中,以老式方式遍历数组是否更快,
for (int i = 0; i < a.length; i++)
f(a[i]);
或者使用更简洁的形式,
for (Foo foo : a)
f(foo);
对于 ArrayList,答案是否相同?
当然,对于大量的应用程序代码,答案是它没有明显的区别,因此应该使用更简洁的形式以提高可读性。但是,我正在查看的上下文是重型技术计算,必须执行数十亿次的操作,因此即使是微小的速度差异最终也可能很重要。
在Java中,以老式方式遍历数组是否更快,
for (int i = 0; i < a.length; i++)
f(a[i]);
或者使用更简洁的形式,
for (Foo foo : a)
f(foo);
对于 ArrayList,答案是否相同?
当然,对于大量的应用程序代码,答案是它没有明显的区别,因此应该使用更简洁的形式以提高可读性。但是,我正在查看的上下文是重型技术计算,必须执行数十亿次的操作,因此即使是微小的速度差异最终也可能很重要。
如果您正在遍历一个数组,那没关系 - 增强的 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 到更多类似的代码。
建议:如果您真的认为它可能会产生重大影响(只有在循环体绝对很小的情况下才会这样做),那么您应该用您的实际应用程序对其进行基准测试。这是唯一重要的情况。
这完全属于微优化领域。真的没关系。从风格上讲,我总是更喜欢第二种,因为它更简洁,除非你需要循环计数器来做其他事情。这比这种微优化更重要:可读性。
话虽这么说,对于 ArrayList 不会有太大区别,但 LinkedList 与第二个相比效率更高。
测量它。所有性能问题的答案可能取决于 VM 版本、处理器、内存速度、缓存等。因此您必须针对您的特定平台对其进行测量。
我个人更喜欢第二种变体,因为意图更清楚。如果性能成为问题,我无论如何都可以稍后对其进行优化——如果该代码对整个应用程序的性能真的很重要。
对于链表:
for(ClassOfElement element : listOfElements) {
System.out.println(element.getValue());
}
之前有人回答:
在数组或 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以查看您的代码实际花费的时间。
更快的是使用 fork-join 框架的 ParallelArray(如果你有足够大的数据集)。