Heim  >  Artikel  >  Java  >  Vergleichende Analyse von For- und For-each-Anwendungen in Java-Schleifen

Vergleichende Analyse von For- und For-each-Anwendungen in Java-Schleifen

王林
王林nach vorne
2023-05-25 14:56:081189Durchsuche

for-each-Implementierungsmethode

For-each ist keine neue Syntax, sondern Syntaxzucker für Java. Zur Kompilierungszeit konvertiert der Compiler diesen Code in eine Iterator-Implementierung und kompiliert ihn in Bytecode. Wir können den folgenden kompilierten Code dekompilieren, indem wir den Befehl javap-verbose-Testforeach ausführen: 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

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);

Der erhaltene detaillierte Bytecode lautet wie folgt:

rrreee

Die allgemeine Bedeutung dieses Bytecodes ist die Verwendung von getfileld , um die Variable integers abzurufen und List.iterator aufzurufen, um die Iteratorinstanz abzurufen und iterator.hasNext aufzurufen. Wenn true zurückgegeben wird, rufen Sie die Methode iterator.next auf.

Bitte beachten Sie, dass dies die Implementierungslogik des Iterators ist, der die Sammlung durchläuft.

Benchmarking

Jetzt testen wir die Verwendung der for-Loop-Methode und der for-each-Methode.

rrreeeVergleichende Analyse von For- und For-each-Anwendungen in Java-SchleifenHier sind die Testergebnisse:

Wie Sie sehen können, sind die Ergebnisse offensichtlich. Die Verwendung der For-Schleifenmethode ist bei ArrayList effizienter als die For-Each-Methode.


Können wir sagen, dass die for-Schleife besser ist als die for-each?

Die Antwort ist nein. Im nächsten Benchmark ändern wir die ArrayList in eine LinkedList. Vergleichende Analyse von For- und For-each-Anwendungen in Java-SchleifenHier noch einmal die Testergebnisse.

Ursachenanalyse


Einige Anfänger fragen sich vielleicht, warum ArrayList die for-Schleifenmethode verwendet, um schneller zu durchlaufen, während LinkedList langsamer und sehr langsam ist?

Dies wird durch die Datenstrukturen ArrayList und LinkedList bestimmt.

ArrayList verwendet Arrays, um Elemente darunter zu speichern. Arrays sind zusammenhängende Speicherbereiche. Daten können über Indizes abgerufen werden. Die Zeitkomplexität beträgt O(1), also ist es schnell.

Die unterste Ebene von LinkedList ist eine doppelt verknüpfte Liste. Verwenden Sie eine for-Schleife, um den Durchlauf zu implementieren, und zwar jedes Mal vom Kopfknoten der verknüpften Liste aus. Die Zeitkomplexität beträgt O(n*n).
  • Fazit

  • Die for-Schleifenmethode ist bei Verwendung von ArrayList schneller, da for-each durch einen Iterator implementiert wird und eine gleichzeitige Änderungsüberprüfung durchgeführt werden muss.

  • Bei Verwendung von LinkedList ist for-each viel schneller als for-Schleife, da LinkedList mithilfe einer doppelt verknüpften Liste implementiert wird. Jede Adressierung muss am Kopfknoten beginnen. Vermeiden Sie beim Durchlaufen einer LinkedList die Verwendung von for-Schleifen.

Bei Verwendung des Iteratormusters muss sich for-each nicht um die spezifische Implementierung der Sammlung kümmern. Wenn eine Sammlung ersetzt werden muss, kann dies problemlos durchgeführt werden, ohne den Code zu ändern. 🎜🎜🎜

Das obige ist der detaillierte Inhalt vonVergleichende Analyse von For- und For-each-Anwendungen in Java-Schleifen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen