web-dev-qa-db-fra.com

Java efficacité de la boucle ("for" vs. "foreach")

(Une question pour ceux qui connaissent bien les astuces de compilation et d'optimisation JVM ... :-)

Existe-t-il des modèles "pour" et "foreach" nettement supérieurs à l'autre?

Considérez les deux exemples suivants:

public void forLoop(String[] text)
{
    if (text != null)
    {
        for (int i=0; i<text.length; i++)
        {
            // Do something with text[i]
        }
    }
}

public void foreachLoop(String[] text)
{
    if (text != null)
    {
        for (String s : text)
        {
            // Do something with s, exactly as with text[i]
        }
    }
}

forLoop est-il plus rapide ou plus lent que foreachLoop?

En supposant que dans les deux cas, le tableau text n'ait pas besoin de faire de vérifications d'intégrité, y a-t-il un gagnant clair ou encore trop proche pour passer un appel?

EDIT: Comme indiqué dans certaines réponses, les performances devraient être identiques pour les tableaux, tandis que le modèle "foreach" pourrait être légèrement meilleur pour les types de données abstraits comme une liste. Voir aussi cette réponse qui traite du sujet.

27
PNS

De section 14.14.2 du JLS :

Sinon, l'expression a nécessairement un type de tableau, T []. Soit L1 ... Lm la séquence (éventuellement vide) d'étiquettes précédant immédiatement l'instruction for améliorée. La signification de l'instruction for améliorée est alors donnée par l'instruction for de base suivante:

T[] a = Expression;
L1: L2: ... Lm:
for (int i = 0; i < a.length; i++) {
        VariableModifiersopt Type Identifier = a[i];
        Statement
}

En d'autres termes, je m'attendrais à ce qu'ils finissent par être compilés dans le même code.

Il y a certainement un gagnant clair: la boucle for améliorée est plus lisible . Cela devrait être votre principale préoccupation - vous ne devriez même envisager que de micro-optimiser ce genre de chose lorsque vous avez prouvé que la forme la plus lisible ne jouez aussi bien que vous le souhaitez.

61
Jon Skeet

Vous pouvez écrire votre propre test simple, qui mesure le temps d'exécution.

long start = System.currentTimeMillis();
forLoop(text);
long end = System.currentTimeMillis();
long result = end - start;

le résultat est le temps d'exécution.

4
alnasfire

Étant donné que vous utilisez un type array, la différence de performances n'a pas d'importance. Ils finiraient par donner les mêmes performances après être passés par l'entonnoir optimization.

Mais si vous utilisez des ADT comme List, alors le forEachLoop est évidemment le meilleur choix par rapport à plusieurs appels get(i).

3
Navneeth G

Vous devez choisir l'option qui est plus lisible presque à chaque fois, sauf si vous savez que vous avez un problème de performances.

Dans ce cas, je dirais qu'ils sont garantis d'être les mêmes.

La seule différence est que vous vérifiez en plus text.length qui sera probablement plus lent que rapide.

Je voudrais également m'assurer que le texte n'est jamais nul statiquement. par exemple. en utilisant une annotation @NotNull. Il vaut mieux attraper ces problèmes au moment de la compilation/construction (et ce serait plus rapide)

3
Peter Lawrey

Il n'y a pas de pénalité de performance 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. Pour plus de détails, suivez ceci post .

2
Kuldeep Jain