Maison  >  Article  >  Java  >  Analyse comparative des applications For et For-each dans les boucles Java

Analyse comparative des applications For et For-each dans les boucles Java

王林
王林avant
2023-05-25 14:56:081144parcourir

Méthode d'implémentation for-each

For-each n'est pas une nouvelle syntaxe, mais du sucre de syntaxe pour Java. Au moment de la compilation, le compilateur convertit ce code en implémentation d'itérateur et le compile en bytecode. Nous pouvons décompiler le code compilé suivant en exécutant la commande javap-verbose-Testforeach : 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);

Le bytecode détaillé obtenu est le suivant :

rrreee

La signification générale de ce bytecode est d'utiliser getfileld pour obtenir la variable integers et appelez List.iterator pour obtenir l'instance de l'itérateur et appelez iterator.hasNext. Si true est renvoyé, appelez la méthode iterator.next.

Veuillez voir, il s'agit de la logique d'implémentation de l'itérateur traversant la collection.

Benchmarking

Maintenant, testons en utilisant la méthode de boucle for et la méthode for-each.

rrreeeAnalyse comparative des applications For et For-each dans les boucles JavaVoici les résultats des tests :

Comme vous pouvez le constater, les résultats sont évidents. L’utilisation de la méthode de boucle For est plus efficace sur ArrayList que la méthode For each.


Peut-on dire que la boucle for est meilleure que la boucle for-each ?

La réponse est non. Dans le benchmark suivant, nous changeons ArrayList en LinkedList. Analyse comparative des applications For et For-each dans les boucles JavaEncore une fois, voici les résultats des tests.

Analyse des causes


Certains débutants peuvent se demander pourquoi ArrayList utilise la méthode de boucle for pour parcourir plus rapidement, alors que LinkedList est plus lent et très lent ?

Ceci est déterminé par les structures de données ArrayList et LinkedList.

ArrayList utilise des tableaux pour stocker les éléments en dessous. Les tableaux sont des espaces mémoire contigus. Les données peuvent être obtenues via des index. La complexité temporelle est O(1), donc c'est rapide.

La couche inférieure de LinkedList est une liste doublement chaînée. Utilisez une boucle for pour implémenter le parcours, en commençant à chaque fois à partir du nœud principal de la liste chaînée. La complexité temporelle est O(n*n).
  • Conclusion

  • La méthode de boucle for est plus rapide lors de l'utilisation d'ArrayList car for-each est implémenté par les itérateurs et doit effectuer une vérification des modifications simultanées.

  • Lorsque vous utilisez LinkedList, for-each est beaucoup plus rapide que la boucle for car LinkedList est implémenté en utilisant une liste doublement chaînée. Chaque adressage doit commencer à partir du nœud principal. Lorsque vous parcourez une LinkedList, évitez d'utiliser des boucles for.

En utilisant le modèle itérateur, for-each n'a pas besoin de se soucier de l'implémentation spécifique de la collection. Si une collection doit être remplacée, cela peut être facilement fait sans modifier le code. 🎜🎜🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer