在Java中迭代数组的最快方法:循环variables与增强语句

在Java中,以老式方式遍历数组的速度会更快,

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

或者使用更简洁的forms,

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

对于一个ArrayList,答案是一样的吗?

当然,对于大量的应用程序代码,答案是没有明显的区别,所以应该使用更简洁的forms来提高可读性。 然而,我所看到的背景是重型技术计算,操作必须执行数十亿次,所以即使微小的速度差异可能最终是显着的。

如果循环访问数组,则无关紧要 – 增强的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循环中有更多的设置代码,但它们基本上是做同样的事情。 不涉及迭代器。 此外,我希望他们得到更多的类似的代码。

build议:如果你真的认为它可能会产生重大的不同(如果这个循环的主体绝对是微乎其微的话),那么你应该把它与你真正的应用程序进行比较。 这是唯一重要的情况。

这恰恰落在了微观优化的舞台上。 这真的没关系。 在风格上,我总是比较喜欢第二个,因为它更简洁,除非你需要循环计数器。 这比这种微观优化更重要 :可读性。

这就是说,对于一个ArrayList来说,不会有太大的区别,但是LinkedList会更有效率。

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

我个人更喜欢第二个变体,因为意图更清楚。 如果性能成为问题,我可以稍后对它进行优化 – 如果代码真的对于整个应用程序的性能非常重要。

对于LinkedList:

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

之前有人回答:

for循环和for-each循环之间是否有性能差异?

在一个数组或者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(如果你有足够大的数据集)。