前言
在Java编程中,循环构造是程序员罕用的管制流程,而for循环和foreach循环是其中比拟常见的两种模式。对于它们哪一个更快的探讨始终存在。本文旨在探索Java中的for循环和foreach循环的性能差别,并帮忙读者更好地抉择适宜本身需要的循环形式。通过具体比拟它们的遍历效率、数据结构适用性和编译器优化等因素,咱们将为大家揭示它们的差别和实用场景,以便您可能做出更理智的编程决策。
for循环与foreach循环的比拟
小编认为for和foreach 之间惟一的理论区别是,对于可索引对象,咱们无权拜访索引。
for(int i = 0; i < mylist.length; i++) { if(i < 5) { //do something } else { //do other stuff }}
然而,咱们能够应用 foreach 创立一个独自的索引 int 变量。例如:
int index = -1;for(int myint : mylist) { index++; if(index < 5) { //do something } else { //do other stuff }}
当初写一个简略的类,其中有 foreachTest() 办法,该办法应用 forEach 迭代列表。
import java.util.List;public class ForEachTest { List<Integer> intList; public void foreachTest(){ for(Integer i : intList){ } }}
编译这个类时,编译器会在外部将这段代码转换为迭代器实现。小编通过执行 javap -verbose IterateListTest 反编译代码。
public void foreachTest(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=3, args_size=1 0: aload_0 1: getfield #19 // Field intList:Ljava/util/List; 4: invokeinterface #21, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator; 9: astore_2 10: goto 23 13: aload_2 14: invokeinterface #27, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object; 19: checkcast #33 // class java/lang/Integer 22: astore_1 23: aload_2 24: invokeinterface #35, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z 29: ifne 13 32: return LineNumberTable: line 9: 0 line 12: 32 LocalVariableTable: Start Length Slot Name Signature 0 33 0 this Lcom/greekykhs/springboot/ForEachTest; StackMapTable: number_of_entries = 2 frame_type = 255 /* full_frame */ offset_delta = 13 locals = [ class com/greekykhs/springboot/ForEachTest, top, class java/util/Iterator ] stack = [] frame_type = 9 /* same */
从下面的字节码咱们能够看到:
a). getfield命令用于获取变量整数。
b).调用List.iterator获取迭代器实例
c).调用iterator.hasNext,如果返回true,则调用iterator.next办法。
下边来做一下性能测试。在 IterateListTest 的次要办法中,创立了一个列表并应用 for 和 forEach 循环对其进行迭代。
import java.util.ArrayList;import java.util.List;public class IterateListTest { public static void main(String[] args) { List<Integer> mylist = new ArrayList<>(); for (int i = 0; i < 1000000; i++) { mylist.add(i); } long forLoopStartTime = System.currentTimeMillis(); for (int i = 0; i < mylist.size(); i++) {mylist.get(i);} long forLoopTraversalCost =System.currentTimeMillis()-forLoopStartTime; System.out.println("for loop traversal cost for ArrayList= "+ forLoopTraversalCost); long forEachStartTime = System.currentTimeMillis(); for (Integer integer : mylist) {} long forEachTraversalCost =System.currentTimeMillis()-forEachStartTime; System.out.println("foreach traversal cost for ArrayList= "+ forEachTraversalCost); }}
后果如下:
总结
察看结果显示,for循环的性能优于for-each循环。而后再应用LinkedList比拟它们的性能差别。对于 LinkedList 来说,for-each循环展现出更好的性能。ArrayList外部应用间断存储的数组,因而数据的检索工夫复杂度为 O(1),通过索引能够间接拜访数据。而 LinkedList 应用双向链表构造,当咱们应用 for 循环进行遍历时,每次都须要从链表头节点开始,导致工夫复杂度达到了 O(n*n),因而在这种状况下,for-each 循环更适宜操作 LinkedList。