Itérateur vs pour

On m’a demandé dans une interview quel était l’avantage d’utiliser l’iterator en utilisant pour la boucle ou quel est l’avantage d’utiliser pour iterator en boucle?

Est-ce que n’importe quel corps peut répondre à cela pour qu’à l’avenir Si je fais face à une question similaire alors je peux répondre à cela

Tout d’abord, il existe 2 types de boucles for qui se comportent très différemment. On utilise des indices:

 for (int i = 0; i < list.size(); i++) { Thing t = list.get(i); ... } 

Ce type de boucle n'est pas toujours possible. Par exemple, les listes ont des index, mais les ensembles ne le font pas, car ce sont des collections non ordonnées.

L'autre, la boucle foreach utilise un iterator en coulisse:

 for (Thing thing : list) { ... } 

Cela fonctionne avec tout type de collection Iterable (ou tableau)

Et enfin, vous pouvez utiliser un iterator, qui fonctionne également avec toutes les itérations:

 for (Iterator it = list.iterator(); it.hasNext(); ) { Thing t = it.next(); ... } 

Vous avez donc 3 boucles à comparer.

Vous pouvez les comparer en différents termes: performance, lisibilité, sensibilité aux erreurs, capacité.

Un iterator peut faire des choses qu'une boucle foreach ne peut pas. Par exemple, vous pouvez supprimer des éléments pendant l’itération, si l’iterator le prend en charge:

 for (Iterator it = list.iterator(); it.hasNext(); ) { Thing t = it.next(); if (shouldBeDeleted(thing) { it.remove(); } } 

Les listes offrent également des iterators pouvant itérer dans les deux sens. Une boucle foreach ne se répète que du début à la fin.

Mais un iterator est plus dangereux et moins lisible. Quand une boucle foreach est tout ce dont vous avez besoin, c'est la solution la plus lisible. Avec un iterator, vous pouvez faire ce qui suit, ce qui serait un bug:

 for (Iterator it = list.iterator(); it.hasNext(); ) { System.out.println(it.next().getFoo()); System.out.println(it.next().getBar()); } 

Une boucle foreach ne permet pas qu'un tel bug se produise.

L'utilisation des index pour accéder aux éléments est légèrement plus efficace avec les collections sauvegardées par un tableau. Mais si vous changez d'avis et utilisez un LinkedList au lieu d'un ArrayList, soudainement, les performances seront affreuses, car chaque fois que vous accédez à list.get(i) , la liste liée devra list.get(i) tous ses éléments jusqu'au premier. Un iterator (et donc la boucle foreach) n'a pas ce problème. Il utilise toujours le meilleur moyen possible pour parcourir les éléments de la collection donnée, car la collection elle-même a sa propre implémentation Iterator.

Ma règle générale est la suivante: utilisez la boucle foreach, sauf si vous avez vraiment besoin des capacités d'un iterator. Je n'utiliserais que pour la boucle avec des index avec des tableaux, quand j'ai besoin d'accéder à l'index dans la boucle.

Avantage Itérateur:

  • Possibilité de supprimer des éléments des collections.
  • Possibilité d’avancer et de reculer en utilisant next() et previous() .
  • Possibilité de vérifier s’il y a plus d’éléments ou non en utilisant hasNext() .

Loop a été conçu uniquement pour parcourir une Collection , donc si vous voulez juste parcourir une Collection , il est préférable d’utiliser une boucle telle que for-Each , mais si vous en voulez plus, vous pouvez utiliser Iterator.

si vous accédez aux données par numéro (par exemple “i”), il est rapide lorsque vous utilisez array. parce qu’il va directement à l’élément

Mais, autre structure de données (par exemple, arborescence, liste), elle nécessite plus de temps, car elle part du premier élément vers l’élément cible. quand vous utilisez la liste. Il a besoin de temps O (n). alors, ça doit être lent.

Si vous utilisez un iterator, le compilateur sait où vous êtes. donc il a besoin de O (1) (car, il commence à partir de la position actuelle)

enfin, si vous utilisez uniquement des tableaux ou une structure de données prenant en charge un access direct (par exemple, arraylist sur java). “a [i]” est bon. mais, lorsque vous utilisez une autre structure de données, l’iterator est plus efficace

La principale différence entre Iterator et le classique for loop, mis à part le fait évident d’avoir ou de ne pas avoir access à l’index de l’élément que vous êtes en train d’itérer, est d’utiliser Iterator pour extraire le code client de l’implémentation sous-jacente. élaborer.

Lorsque votre code utilise un iterator, soit sous cette forme

 for(Item element : myCollection) { ... } 

ce formulaire

 Iterator iterator = myCollection.iterator(); while(iterator.hasNext()) { Item element = iterator.next(); ... } 

ou cette forme

 for(Iterator iterator = myCollection.iterator(); iterator.hasNext(); ) { Item element = iterator.next(); ... } 

Ce que votre code dit: “Je ne me soucie pas du type de collection et de son implémentation, je me soucie juste de pouvoir parcourir ses éléments”. Ce qui est généralement la meilleure approche, car cela rend votre code plus découplé.

Par contre, si vous utilisez le classique pour la boucle, comme dans

 for(int i = 0; i < myCollection.size(); i++) { Item element = myCollection.get(i); ... } 

Votre code dit, j'ai besoin de connaître le type de collection, car je dois parcourir ses éléments de manière spécifique, je vais peut-être aussi vérifier les valeurs NULL ou calculer un résultat en fonction de l'ordre d'itération. Ce qui rend votre code plus fragile, car si, à tout moment, le type de collection que vous recevez change, cela affectera le fonctionnement de votre code.

En résumé, la différence n'est pas tellement la vitesse ou l'utilisation de la mémoire, mais plutôt le découplage de votre code afin qu'il soit plus flexible pour faire face aux changements.