60 votes

Le rendement des traditionnels pour la boucle vs Itérateur/foreach en Java

Est-il des résultats de tests de performances disponible en comparant traditionnel pour la boucle vs Itérateur tout en parcourant une liste de tableaux,HashMap et d'autres collections?

Ou tout simplement pourquoi devrais-je utiliser l'Itérateur sur boucle for ou vice-versa?

81voto

sfussenegger Points 16204

En supposant que c'est ce que tu voulais dire:

// traditional for loop
for (int i = 0; i < collection.size(); i++) {
  T obj = collection.get(i);
  // snip
}

// using iterator
Iterator<T> iter = collection.iterator();
while (iter.hasNext()) {
  T obj = iter.next();
  // snip
}

// using iterator internally (confirm it yourself using javap -c)
for (T obj : collection) {
   // snip
}

Itérateur est plus rapide pour les collections sans accès aléatoire (par exemple, TreeSet, HashMap, LinkedList). Pour les tableaux et ArrayLists, les différences de performances devrait être négligeable.

Edit: je crois que les micro-analyse comparative de la racine de joli beaucoup de mal, tout comme au début de l'optimisation. Mais là encore, je pense que c'est bon de ressentir les conséquences de ces tout à fait insignifiantes. Donc j'ai fait un petit test:

  • itérer sur une LinkedList et une liste de tableaux respecively
  • avec 100 000 "aléatoire" des chaînes
  • pour résumer leur longueur (juste quelque chose pour éviter que le compilateur optimise loin la totalité de la boucle)
  • en utilisant tous les 3 boucle de styles (itérateur, pour chaque, avec compteur)

Les résultats sont similaires pour tous, mais avec de comptoir" avec LinkedList. Toutes les cinq autres ont eu moins de 20 millisecondes) pour itérer sur l'ensemble de la liste. À l'aide de list.get(i) sur une LinkedList 100 000 fois a fallu plus de 2 minutes (!) pour terminer (60 000 fois plus lent). Wow! :) Donc il est préférable d'utiliser un itérateur (explicitement ou implicitement en utilisant pour chaque), surtout si vous ne savez pas quel type et la taille de la liste de votre affaire.

22voto

Svante Points 24355

La première raison de l'utilisation d'un itérateur est évident exactitude. Si vous utilisez un index du mode d'emploi, il peut être très anodin off-by-one erreurs que vous ne pouvez voir si vous regardez de très près: avez-vous commencer à 1 ou à 0? Avez-vous fini en length - 1? Avez-vous utilisé < ou <=? Si vous utilisez un itérateur, il est beaucoup plus facile de voir que c'est vraiment une itération à l'ensemble du tableau. "Dites ce que vous faites, faites ce que vous dites."

La deuxième raison, c'est un accès uniforme aux différentes structures de données. Un tableau peut être consulté de manière efficace par le biais d'un indice, mais une liste chaînée est le mieux traversé par de rappeler le dernier élément accessible (dans le cas contraire, vous obtenez un "Shlemiel le peintre"). Une table de hachage est encore plus compliqué. En fournissant une interface uniforme de ces et d'autres structures de données (par exemple, vous pouvez également faire de l'arbre traversals), vous obtenez évident exactitude de nouveau. La traversée de la logique doit être mise en œuvre qu'une seule fois, et le code de l'aide, il peut, de façon concise, "dire ce qu'il fait et de faire ce qu'il dit."

5voto

KLE Points 11711

La Performance est similaire dans la plupart des cas.

Toutefois, lorsqu'un code reçoit une Liste, et les boucles, c'est que des cas bien connu:
l'Itérateur est meilleur pour l'ensemble de la Liste des implémentations qui ne mettent pas en œuvre RandomAccess (exemple: LinkedList).

La raison en est que ces listes, l'accès à un élément d'index n'est pas une constante de temps de l'opération.

Ainsi, vous pouvez également envisager l'Itérateur comme plus robuste (pour les détails de mise en œuvre).


Comme toujours, la performance ne devrait pas se cacher la lisibilité des questions.
Le java5 boucle foreach est un grand succès sur cet aspect :-)

2voto

MeBigFatGuy Points 12489

Je ne crois pas que

for (T obj : collection) {

calcule .size() à chaque fois à travers la boucle et est donc plus rapide que

for (int i = 0; i < collection.size(); i++) {

1voto

Paul Wagland Points 10487

L'utilisation de JAD ou JD-GUI à l'encontre de votre code généré, vous verrez qu'il n'y a pas de différence réelle. L'avantage de la nouvelle itérateur est qu'il ressemble de nettoyage dans votre base de code.

Edit: je vois de l'autre les réponses que vous vouliez vraiment dire la différence entre l'utilisation de get(i) par rapport à un itérateur. J'ai pris la question originale pour faire la différence entre les anciennes et les nouvelles façons d'utiliser l'itérateur.

À l'aide de get(i) et de maintenir votre propre compteur, en particulier pour l' List des classes n'est pas une bonne idée, pour les raisons mentionnées dans la accepté de répondre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X