Java Language
Itérateur et Iterable
Recherche…
Introduction
java.util.Iterator
est l'interface Java SE standard pour les objets qui implémentent le modèle de conception Iterator. L'interface java.lang.Iterable
est destinée aux objets pouvant fournir un itérateur.
Remarques
Il est possible d'itérer sur un tableau en utilisant la boucle for
-each, bien que les tableaux Java n'implémentent pas Iterable; l'itération est effectuée par JVM en utilisant un index non accessible en arrière-plan.
Utiliser Iterable en boucle
Les cours de mise en œuvre Iterable<>
l' interface peuvent être utilisés dans for
boucles. Ce n'est en fait que du sucre syntaxique pour obtenir un itérateur à partir de l'objet et l'utiliser pour obtenir tous les éléments de manière séquentielle; cela rend le code plus clair, plus rapide à écrire et moins sujet aux erreurs.
public class UsingIterable {
public static void main(String[] args) {
List<Integer> intList = Arrays.asList(1,2,3,4,5,6,7);
// List extends Collection, Collection extends Iterable
Iterable<Integer> iterable = intList;
// foreach-like loop
for (Integer i: iterable) {
System.out.println(i);
}
// pre java 5 way of iterating loops
for(Iterator<Integer> i = iterable.iterator(); i.hasNext(); ) {
Integer item = i.next();
System.out.println(item);
}
}
}
Utiliser l'itérateur brut
Bien que l'utilisation de la boucle foreach (ou "extended for loop") soit simple, il est parfois utile d'utiliser directement l'itérateur. Par exemple, si vous souhaitez générer un ensemble de valeurs séparées par des virgules, mais ne souhaitez pas que le dernier élément comporte une virgule:
List<String> yourData = //...
Iterator<String> iterator = yourData.iterator();
while (iterator.hasNext()){
// next() "moves" the iterator to the next entry and returns it's value.
String entry = iterator.next();
System.out.print(entry);
if (iterator.hasNext()){
// If the iterator has another element after the current one:
System.out.print(",");
}
}
C'est beaucoup plus facile et plus clair que d'avoir une variable isLastEntry
ou de faire des calculs avec l'index de boucle.
Créer votre propre Iterable.
Pour créer votre propre Iterable comme avec n'importe quelle interface, il vous suffit d'implémenter les méthodes abstraites dans l'interface. Pour Iterable
il n'y en a qu'un qui s'appelle iterator()
. Mais son type de retour Iterator
est lui-même une interface avec trois méthodes abstraites. Vous pouvez retourner un itérateur associé à une collection ou créer votre propre implémentation personnalisée:
public static class Alphabet implements Iterable<Character> {
@Override
public Iterator<Character> iterator() {
return new Iterator<Character>() {
char letter = 'a';
@Override
public boolean hasNext() {
return letter <= 'z';
}
@Override
public Character next() {
return letter++;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Doesn't make sense to remove a letter");
}
};
}
}
Utiliser:
public static void main(String[] args) {
for(char c : new Alphabet()) {
System.out.println("c = " + c);
}
}
Le nouvel Iterator
doit être associé à un état indiquant le premier élément, chaque appel à la prochaine actualisant son état pour indiquer le suivant. Le hasNext()
vérifie si l'itérateur est à la fin. Si l'itérateur était connecté à une collection modifiable, la méthode facultative remove()
l'itérateur pourrait être implémentée pour supprimer l'élément actuellement pointé de la collection sous-jacente.
Suppression d'éléments à l'aide d'un itérateur
La méthode Iterator.remove()
est une méthode facultative qui supprime l'élément renvoyé par l'appel précédent à Iterator.next()
. Par exemple, le code suivant remplit une liste de chaînes puis supprime toutes les chaînes vides.
List<String> names = new ArrayList<>();
names.add("name 1");
names.add("name 2");
names.add("");
names.add("name 3");
names.add("");
System.out.println("Old Size : " + names.size());
Iterator<String> it = names.iterator();
while (it.hasNext()) {
String el = it.next();
if (el.equals("")) {
it.remove();
}
}
System.out.println("New Size : " + names.size());
Sortie:
Old Size : 5
New Size : 3
Notez que le code ci-dessus est un moyen sûr de supprimer des éléments lors de l'itération d'une collection type. Si, au contraire, vous tentez de supprimer des éléments d'une collection comme ceci:
for (String el: names) {
if (el.equals("")) {
names.remove(el); // WRONG!
}
}
une collection typique (telle que ArrayList
) qui fournit aux itérateurs une sémantique d'itérateur rapide échoue pour lancer une ConcurrentModificationException
.
La méthode remove()
ne peut être appelée qu'une seule fois après un appel next()
. S'il est appelé avant d'appeler next()
ou s'il est appelé deux fois après un appel next()
appel remove()
lancera une IllegalStateException
.
L'opération de remove
est décrite comme une opération facultative ; Autrement dit, tous les itérateurs ne le permettront pas. Les exemples où il n'est pas pris en charge incluent les itérateurs pour les collections immuables, les vues en lecture seule des collections ou les collections de taille fixe. Si remove()
est appelée lorsque l'itérateur ne prend pas en charge la suppression, une UnsupportedOperationException
sera lancée.