pourquoi le renforcement de la boucle for plus efficace que la normale pour la boucle
J'ai lu que la amélioré pour la boucle est plus efficace que la normale pour la boucle ici:
http://developer.android.com/guide/practices/performance.html#foreach
Quand j'ai cherché la différence entre leur efficacité, tout ce que je trouve est: Dans le cas de la normale pour la boucle nous avons besoin d'une étape supplémentaire, à savoir la longueur de la matrice ou de la taille, etc.,
for(Integer i : list){
....
}
int n = list.size();
for(int i=0; i < n; ++i){
....
}
Mais est-ce la seule raison, le renforcement de la boucle for est mieux que la normale pour la boucle? Dans ce cas, mieux utiliser la normale pour la boucle en raison de la légère complexité dans la compréhension de la renforcée pour la boucle.
Vérifier cela pour une question intéressante: http://www.coderanch.com/t/258147/java-programmer-SCJP/certification/Enhanced-Loop-Vs-Loop
Peut-on expliquer la mise en œuvre interne de ces deux types de boucles for, ou d'expliquer d'autres raisons d'utiliser le renforcement de la pour la boucle?
je l'ai lu ici...mais il n'y a pas d'explication pourquoi il en est ainsi: developer.android.com/guide/practices/performance.html#foreach
"Pour résumer: utiliser l'interface de boucle par défaut, mais imaginez un écrit à la main compté boucle pour la performance est critique ArrayList itération." Qui dit le contraire de ce que vous lisez: Pour ArrayList, la deuxième solution est plus rapide.
en fait, il y a une explication: "
zero()
est plus lent, parce que l'équipe ne peut pas encore optimiser loin le coût d'obtention de la longueur du tableau une fois pour chaque itération de la boucle.". Qui ressemble à une explication pour moi.laisser le zéro()...c'est la pire façon de boucle...mais que dire d'une()?? ma question est un() et deux() n'ont pas de différence tout en parcourant les tableaux(dans le cas de java)...mais dans android mieux, j'ai utiliser les deux (), même pour les tableaux??
OriginalL'auteur Archie.bpgc | 2012-07-19
Vous devez vous connecter pour publier un commentaire.
C'est un peu simpliste de dire que l'amélioration de la boucle for est plus efficace. Il peut être, mais dans de nombreux cas, il est presque exactement la même chose qu'une vieille école de la boucle.
La première chose à noter est que pour les collections de la renforcée pour la boucle utilise un
Iterator
, donc si vous avez manuellement itérer sur une collection à l'aide d'unIterator
alors vous devriez avoir à peu près la même performance que le renforcement de la boucle for.Un endroit où le renforcement de la boucle for est plus rapide qu'un naïvement mis en œuvre traditionnelle boucle est quelque chose comme ceci:
Dans ce cas, la Boucle 1 sera plus lente que celle de la Boucle 2 et de la Boucle 3, car il aura à (partiellement) la traversée de la liste à chaque itération de trouver l'élément à la position
i
. La boucle 2 et 3, cependant ne jamais l'étape un élément de plus dans la liste, en raison de l'utilisation d'unIterator
. La boucle 2 et 3 auront aussi à peu près la même performance depuis la Boucle 3 est à peu près exactement ce que le compilateur produira lorsque vous écrivez du code dans la Boucle 2.la différence, finalement, semble à accès Aléatoire et accès Série de la collection, dans l'exemple cité. Pour un tableau, à la fois la boucle types se comportent de la même.
mais dans le lien ici developer.android.com/guide/practices/... donne l'exemple d'un Tableau...donc selon vous une explication nous n'avons pas besoin d'utiliser foreach lors de la traversée d'un tableau de droite??
c'est correct.
tout d'abord: Android est différent de "Java". Le Dalvik VM n'est pas (encore) aussi bien à l'optimisation de la HotSpot VM, donc il y aura des endroits où les performances des suggestions pour Android diffèrent de "normal" de Java. C'est l'un de ces cas. Lire la documentation précisément: en particulier les exemples
one
,two
etthree
sera probablement être tout à fait semblable dans la performance sur "normal" de la JVM.OriginalL'auteur Joachim Sauer
Je suis moi-même surpris dans un peu d'expérience que j'ai faite aujourd'hui avec les points mentionnés ci-dessus.
Donc, ce que j'ai fait est que j'ai inséré un certain nombre d'éléments d'une liste, et réitéré par le biais de l'aide de l'mentionnés ci-dessus trois méthodes 1)utilisation des fonctions avancées pour la boucle 2) à l'aide d'un Itérateur 3) à l'aide de simple boucle et get()
Je suppose que les programmeurs comme vous les gars, vous pouvez mieux comprendre ce que j'ai fait en voyant le code.
Les résultats, si pas ce que j'attendais . Voici le graphique des temps écoulé dans 3 cas.
Axe Y-temps écoulé
De l'axe X-cas de test
test de décision1:10 entrées
test case2:30 entrées
test case3:50 entrées
test case4:100 entrées
test case5:150 entrées
test case6:300 entrées
test case7:500 entrées
test case8:1000 entrées
test case9:2000 entrées
test case10:5000 entrées
test case11:10000 entrées
test cas12:100000 entrées
Ici, vous pouvez voir que la simple boucle effectue de façon mieux que d'autres.si vous trouvez des erreurs dans le code ci-dessus , ne répondre et je vais vérifier à nouveau. à jour sur cette nouvelle après je creuser par le biais de bytecode et de voir ce qui se passe sous le capot.
Mes excuses pour cette longue réponse, mais je tiens à être descriptive.
Philip
Avez-vous déjà réorganisé les cas de test? La raison pour laquelle la première mise en œuvre est plus lent peut-être en raison de défauts de cache (les objets ne sont pas encore dans le cache)...
Oui , comme une question de fait , je réorganisées et essayé. je ne sais pas si JIT est jouer avec l'indice de référence. mais quand j'ai jeté un coup d'oeil dans le bytecode, il montre que la simple boucle fonctionne mieux .
Il dépend de la structure de données. Si vous utilisez LinkedList, vous verrez image complètement différente.
OriginalL'auteur Philip George
En fait parfois, c'est moins efficace pour le programme, mais la plupart du temps son exactement la même.
Son plus efficace pour le développeur, ce qui est souvent beaucoup plus important
Une boucle for-each est particulièrement utile lors de l'itération sur une collection.
est plus facile à écrire (mais fait la même chose que, de sorte que son pas plus efficace pour le programme)
À l'aide de la "vieille" la boucle est légèrement plus efficace lors de l'accès au hasard de collecte accessible par l'index.
À l'aide d'une boucle for-each sur une collection toujours utilise un Itérateur qui est légèrement moins efficace pour un accès aléatoire listes.
Autant que je sache, l'utilisation d'une boucle for-each est jamais plus efficace pour le programme, mais comme je l'ai dit, l'efficacité du développeur est souvent beaucoup plus important.
Comme quelqu'un d'autre points ci-dessus, un mal écrit vieille école de la boucle for peut être moins efficace que la nouvelle for-each. Donc, maintenant vous savez d'un cas où une boucle for-each EST plus efficace pour le programme.
À l'aide d'une boucle for-each signifie que vous êtes moins susceptible d'écrire quelque chose d'inefficace. Toutefois, si vous savez ce que vous faites, le byte code pour-chaque produit est exactement le même que vous, vous pouvez écrire vous-même, mais est une courte distance de la main. À partir d'un octet de code de niveau il n'y a aucun moyen de faire la différence pour vous (attendre le générés locales, les noms de variables sont a donner). Bien écrit, le code sera le même dans les deux cas. Si vous avez une liste de tableaux, indexé pour la boucle est légèrement plus efficace que l'utilisation d'un for-each, qui utilise un itérateur.
OriginalL'auteur Peter Lawrey
Pour chacun utilise l'interface Iterator. Je me doute que c'est plus efficace que le "vieux style". L'Itérateur doit également vérifier la taille de la liste.
C'est surtout pour des raisons de lisibilité.
Il devrait être plus rapide pour les non-random-access collections comme LinkedList, mais alors la comparaison est injuste. Vous n'auriez pas utilisé à la deuxième mise en œuvre (avec la lenteur de l'accès indexé) de toute façon.
OriginalL'auteur Thilo
La boucle foreach est aussi efficace que ce type de boucle:
parce que c'est strictement équivalent.
Si vous itérer sur une liste à l'aide de
Puis la boucle foreach va avoir des performances équivalentes que votre boucle, mais seulement pour ArrayList. Dans le cas d'une LinkedList, votre boucle sera catastrophique de la performance, car à chaque iteratioon, il devra parcourir tous les nœuds de la liste jusqu'à ce qu'il arrive à la
i
élément th.La boucle foreach (ou la boucle basée sur un itérateur, qui est la même), n'ont pas ce problème, puisque l'itérateur maintient une référence vers le nœud courant et va tout simplement à l'autre, à chaque itération. C'est le bast choix, car il fonctionne très bien avec tous les types de listes. Il exprime aussi l'intention plus clairement, et il est plus sûr parce que vous ne prenez pas le risque d'un accroissement de l'indice à l'intérieur de la boucle, ou d'utiliser le mauvais indice dans le cas de boucles imbriquées.
Ce n'est pas récursive vs itératif. C'est juste que le
get()
opération, sur une liste liée, consiste à partir du premier noeud, et d'obtenir la suivante jusqu'à ce que l'indice de je. C'est un O(n) opérations plutôt que de O(1) dans le cas d'une liste de tableaux. Obtenir l'élément suivant à partir d'un itérateur est toujours en O(1). Si la liste est une liste de tableaux ou d'une LinkedList n'a pas d'importance: la performance est aussi bon qu'il peut l'être.Si vous utilisez
LinkedList
(intensivement), alors vous êtes susceptibles d'avoir insondable performance de toute façon.OriginalL'auteur JB Nizet
Efficaces Java :
Mais Josh Bloch n'est pas de décrire comment la JVM optimise.
OriginalL'auteur Geek
toutes les réponses sont bonnes,et je pense ne plus les réponses sont nécessaires, mais je veux juste souligner que:
Le renforcement de l'énoncé peut être utilisé seulement à
obtain array elements
il ne peut pas être utilisé à
modify elements
.Si votre programme a besoin de modifier des éléments, utiliser le traditionnel contre-contrôlé
for
déclaration.prendre un coup d'oeil
Nous ne pouvions pas utiliser le
enhanced for
déclaration parce que nous sommesmodifying the array’s elements
.OriginalL'auteur Basheer AL-MOMANI