web-dev-qa-db-fra.com

Pourquoi Android Studio veut-il que j'utilise For Each au lieu de For Loop?

Cette question me lutte depuis longtemps. Pourquoi parfois Android Studio veut que j'utilise For Each au lieu de For Loop, car lorsque j'utilise For Loop, je reçois un avertissement que je pourrais utiliser pour chacun (et avec Alt + Entrez-le me suggère l'autofix).

Par exemple, supposons que nous ayons ce code

String a = "";
String[] array = {"A","B","C"};

for(int i = 0; i < array.length; i++) {
    a += array[i];
    a += ",";
}

Je reçois un avertissement

et c'est le correctif suggéré par Android Studio

for (String anArray : array) {
        a += anArray;
        a += ",";
}

Est-ce plus performant? Il y a une raison pour laquelle je devrais obtenir un avertissement pour réellement utiliser juste pour la boucle?

Ou quand c'est mieux pour la boucle ou pour chacun?

10
user1714647

Extrait du livre: Effective Java (2nd Edition) by Joshua Bloch

La boucle for-each, introduite dans la version 1.5, élimine l'encombrement et la possibilité d'erreur en masquant complètement l'itérateur ou la variable d'index. L'idiome résultant s'applique également aux collections et aux tableaux:

    // The preferred idiom for iterating over collections and arrays
     for (Element e : elements) {
         doSomething(e);
     }

Lorsque vous voyez le deux-points (:), lisez-le comme "in". Ainsi, la boucle ci-dessus se lit comme "pour chaque élément e dans les éléments". Notez qu'il n'y a pas de pénalité de performances pour l'utilisation de la boucle for-each, même pour les tableaux. En fait, il peut offrir un léger avantage en termes de performances par rapport à une boucle for ordinaire dans certaines circonstances, car il ne calcule la limite de l'index du tableau qu'une seule fois. Bien que vous puissiez le faire à la main (point 45), les programmeurs ne le font pas toujours.


Voici une comparaison de http://developer.Android.com/training/articles/perf-tips.html#Loops :

static class Foo {
    int mSplat;
}

Foo[] mArray = ...

public void zero() {
    int sum = 0;
    for (int i = 0; i < mArray.length; ++i) {
        sum += mArray[i].mSplat;
    }
}

public void one() {
    int sum = 0;
    Foo[] localArray = mArray;
    int len = localArray.length;

    for (int i = 0; i < len; ++i) {
        sum += localArray[i].mSplat;
    }
}

public void two() {
    int sum = 0;
    for (Foo a : mArray) {
        sum += a.mSplat;
    }
}

zero() est la plus lente, car le JIT ne peut pas encore optimiser le coût d'obtention de la longueur du tableau une fois pour chaque itération dans la boucle.

one() est plus rapide. Il extrait tout dans les variables locales, évitant les recherches. Seule la longueur de la baie offre un avantage en termes de performances.

two() est plus rapide pour les appareils sans JIT, et ne se distingue pas de one() pour les appareils avec JIT. Il utilise la syntaxe améliorée pour la boucle introduite dans la version 1.5 du langage de programmation Java.

Par conséquent, vous devez utiliser la boucle for améliorée par défaut, mais envisagez une boucle comptée manuscrite pour l'itération ArrayList critique pour les performances.

28
Riddhesh Sanghvi

Il est juste plus lisible lorsque vous répétez simplement sans regarder en avant ou en arrière. Eh bien, c'est lisible si vous choisissez un bon nom de variable (contrairement à anArray pour un String: D). C'est aussi un peu plus sûr parce que si vous étiez un programmeur vraiment stupide, vous pourriez écrire array[2 * i] et lancez un ArrayOutOfBoundsException. En dehors de cela, je trouve un peu exagéré de vous demander de refactoriser cela ... c'est un idiome courant en Java.

1
Dici