乐趣区

关于java:Java-中for循环和foreach循环哪个更快

前言

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

退出移动版