前言
在 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。