首頁  >  文章  >  Java  >  Java循環中的For與For-each應用比較分析

Java循環中的For與For-each應用比較分析

王林
王林轉載
2023-05-25 14:56:081189瀏覽

for-each實作方法

For-each不是一種新語法,而是Java的語法糖。在編譯時,編譯器將此程式碼轉換為迭代器實現,並將其編譯為字節碼。我們可以透過執行指令javap-verbose-Testforeach反編譯以下編譯程式碼:

public class TestForeach {
    List<Integer> integers;
    public void testForeach(){
        for(Integer i : integers){

        }
    }
}

取得的詳細字節碼如下:

public void testForeach();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=3, args_size=1
         0: aload_0
         1: getfield      #2                  // Field integers:Ljava/util/List;
         4: invokeinterface #3,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
         9: astore_1
        10: aload_1
        11: invokeinterface #4,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
        16: ifeq          32
        19: aload_1
        20: invokeinterface #5,  1            // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
        25: checkcast     #6                  // class java/lang/Integer
        28: astore_2
        29: goto          10
        32: return
      LineNumberTable:
        line 11: 0
        line 13: 29
        line 14: 32
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           29       0     2     i   Ljava/lang/Integer;
            0      33     0  this   Ltest/TestForeach;
}

此字節碼的一般意義是使用getfileld指令來取得integers變數並且呼叫List.iterator來取得迭代器實例和呼叫iterator.hasNext。如果傳回true,呼叫iterator.next方法。

請看,這是迭代器遍歷集合的實作邏輯。

基準測試

現在讓我們使用for迴圈方法和for-each方法進行測試。

public class ForLoopTest {

    public static void main(String[] args) {
        List<Integer> arrayList = new ArrayList<>();
        for (int i = 0; i < 10000000; i++) {
            arrayList.add(i);
        }

        long arrayListStartTime = System.currentTimeMillis();
        for (int i = 0; i < arrayList.size(); i++) {
            arrayList.get(i);
        }

        long arrayListCost =System.currentTimeMillis()-arrayListStartTime;
        System.out.println("ArrayList for loop traversal cost: "+ arrayListCost);

        long arrayListForeachStartTime = System.currentTimeMillis();
        for (Integer integer : arrayList) {

        }

        long arrayListForeachCost =System.currentTimeMillis()-arrayListForeachStartTime;
        System.out.println("ArrayList foreach traversal cost: "+ arrayListForeachCost);

這是測試結果:

Java循環中的For與For-each應用比較分析

如你所見,結果是顯而易見的。使用For循環方法比For each方法在ArrayList上表現更有效率。

我們可以說for迴圈比for-each好嗎?

答案是否定的。在下一個基準測試中,我們將ArrayList改為LinkedList。
同樣,這裡是測試結果。

Java循環中的For與For-each應用比較分析

原因分析

有些初學者可能想知道為什麼ArrayList使用for迴圈方法遍歷得更快,而LinkedList則更慢,速度也非常慢?

這由ArrayList和LinkedList資料結構決定。
ArrayList底層使用陣列儲存元素。數組是連續的記憶體空間。數據可以透過索引取得。時間複雜度為O(1),因此速度很快。

LinkedList的底層是一個雙向鍊錶。使用for迴圈實作遍歷,每次都需要從鍊錶的頭節點開始。時間複雜度為O(n*n)。

結論

  • 使用ArrayList時,for循環方法更快,因為for-each由迭代器實現,並且需要執行並發修改驗證。

  • 使用LinkedList時,for-each比for循環快得多,因為LinkedList是透過使用雙向鍊錶來實現的。每個尋址都需要從頭節點開始。遍歷LinkedList時,避免使用for迴圈。

  • 使用迭代器模式,for-each不需要關心集合的具體實作。如果需要替換集合,無需修改程式碼即可輕鬆替換。

#

以上是Java循環中的For與For-each應用比較分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除