Un guide sur Iterator en Java

1. Introduction

Un itérateur est l'un des nombreux moyens de parcourir une collection et, comme chaque option, il a ses avantages et ses inconvénients.

Il a été introduit pour la première fois dans Java 1.2 en remplacement des énumérations et:

  • introduit des noms de méthodes améliorés
  • a permis de supprimer des éléments d'une collection sur laquelle nous itérons
  • ne garantit pas l'ordre d'itération

Dans ce tutoriel, nous allons passer en revue l' interface simple d' Iterator pour savoir comment nous pouvons utiliser ses différentes méthodes.

Nous allons également vérifier l' extension ListIterator plus robuste qui ajoute des fonctionnalités intéressantes.

2. L' interface Iterator

Pour commencer, nous devons obtenir un itérateur à partir d'une collection ; cela se fait en appelant la méthode iterator () .

Pour plus de simplicité, nous obtiendrons l' instance Iterator à partir d'une liste:

List items = ... Iterator iter = items.iterator();

L' interface Iterator a trois méthodes principales:

2.1. hasNext ()

La méthode hasNext () peut être utilisée pour vérifier s'il reste au moins un élément à parcourir.

Il est conçu pour être utilisé comme condition dans les boucles while :

while (iter.hasNext()) { // ... }

2.2. prochain()

La méthode next () peut être utilisée pour passer au-dessus de l'élément suivant et l'obtenir:

String next = iter.next();

Il est recommandé d' utiliser hasNext () avant de tenter d'appeler next () .

Les itérateurs pour les collections ne garantissent pas l'itération dans un ordre particulier, sauf si une implémentation particulière le fournit.

2.3. retirer()

Enfin, si nous voulons supprimer l'élément courant de la collection, nous pouvons utiliser la commande remove:

iter.remove();

Il s'agit d'un moyen sûr de supprimer des éléments lors d'une itération sur une collection sans risque d' exception ConcurrentModificationException.

2.4. Exemple d' itérateur complet

Maintenant, nous pouvons tous les combiner et voir comment nous utilisons les trois méthodes ensemble pour le filtrage des collections:

while (iter.hasNext()) { String next = iter.next(); System.out.println(next); if( "TWO".equals(next)) { iter.remove(); } }

C'est ainsi que nous utilisons couramment un itérateur, nous vérifions à l'avance s'il y a un autre élément, nous le récupérons et ensuite nous effectuons une action dessus.

2.5. Itération avec des expressions Lambda

Comme nous l'avons vu dans les exemples précédents, il est très verbeux d'utiliser un Iterator lorsque nous voulons juste passer en revue tous les éléments et faire quelque chose avec eux.

Depuis Java 8, nous avons la méthode forEachRemaining qui permet l'utilisation de lambdas pour traiter les éléments restants:

iter.forEachRemaining(System.out::println);

3. L' interface ListIterator

ListIterator est une extension qui ajoute de nouvelles fonctionnalités pour itérer sur des listes:

ListIterator listIterator = items.listIterator(items.size());

Remarquez comment nous pouvons fournir une position de départ qui dans ce cas est la fin de la liste.

3.1. hasPrevious () et précédent ()

ListIterator peut être utilisé pour la traversée vers l'arrière afin de fournir des équivalents de hasNext () et next () :

while(listIterator.hasPrevious()) { String previous = listIterator.previous(); }

3.2. nextIndex () et previousIndex ()

De plus, nous pouvons parcourir des indices et non des éléments réels:

String nextWithIndex = items.get(listIterator.nextIndex()); String previousWithIndex = items.get(listIterator.previousIndex());

Cela pourrait s'avérer très utile au cas où nous aurions besoin de connaître les index des objets que nous modifions actuellement, ou si nous souhaitons conserver un enregistrement des éléments supprimés.

3.3. ajouter()

La méthode add , qui, comme son nom l'indique, permet d'ajouter un élément avant l'élément qui serait retourné par next () et après celui retourné par previous ():

listIterator.add("FOUR");

3.4. ensemble()

La dernière méthode qui mérite d'être mentionnée est set (), qui nous permet de remplacer l'élément qui a été renvoyé lors de l'appel à next () ou previous () :

String next = listIterator.next(); if( "ONE".equals(next)) { listIterator.set("SWAPPED"); }

Il est important de noter que cela ne peut être exécuté que si aucun appel préalable à add () ou remove () n'a été effectué.

3.5. Exemple de ListIterator complet

Nous pouvons maintenant les combiner tous pour en faire un exemple complet:

ListIterator listIterator = items.listIterator(); while(listIterator.hasNext()) { String nextWithIndex = items.get(listIterator.nextIndex()); String next = listIterator.next(); if("REPLACE ME".equals(next)) { listIterator.set("REPLACED"); } } listIterator.add("NEW"); while(listIterator.hasPrevious()) { String previousWithIndex = items.get(listIterator.previousIndex()); String previous = listIterator.previous(); System.out.println(previous); }

Dans cet exemple, nous commençons par obtenir le ListIterator à partir de la liste , puis nous pouvons obtenir l'élément suivant soit par index - qui n'augmente pas l'élément courant interne de l'itérateur - soit en appelant next .

Ensuite, nous pouvons remplacer un élément spécifique par set et en insérer un nouveau avec add.

Après avoir atteint la fin de l'itération, nous pouvons revenir en arrière pour modifier des éléments supplémentaires ou simplement les imprimer de bas en haut.

4. Conclusion

L' interface Iterator nous permet de modifier une collection en la parcourant, ce qui est plus difficile avec une simple instruction for / while. Ceci, à son tour, nous donne un bon modèle que nous pouvons utiliser dans de nombreuses méthodes qui ne nécessitent que le traitement des collections tout en maintenant une bonne cohésion et un faible couplage.

Enfin, comme toujours, le code source complet est disponible sur GitHub.