Lors de l'apprentissage de la collection en Java, j'ai remarqué que l'interface racine Collection du niveau collection implémente l'interface Iterable
1. Iterator Iterator
Interface : Iterator
public interface Iterator<E>{ boolean hasNext(); E next(); void remove(); }
En regardant l'API de l'interface Iterator, vous pouvez savoir qu'il s'agit d'un itérateur pour parcourir la collection. Les itérateurs permettent à l'appelant de supprimer des éléments de la collection pointée par l'itérateur lors de l'itération en utilisant une sémantique bien définie.
Il convient de noter en particulier l'utilisation de la méthode Remove() de cet itérateur : supprimer le dernier élément renvoyé par l'itérateur (opération facultative) de la collection pointée par l'itérateur. Cette méthode ne peut être appelée qu'une seule fois par appel au suivant. Si la collection pointée par l'itérateur est modifiée lors d'une itération autrement qu'en appelant cette méthode (méthode Remove), le comportement de l'itérateur n'est pas défini. Le concepteur de l'interface a souligné lors de la conception de l'interface Iterator
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class ItaratorTest { public static void main(String[] args) { Collection<String> list = new ArrayList<String>(); list.add("Android"); list.add("IOS"); list.add("Windows Mobile"); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String lang = iterator.next(); list.remove(lang);//will throw ConcurrentModificationException } } }
Ce code lancera une exception ConcurrentModificationException lors de l'exécution, car nous n'en avons aucune utilité pendant l'itérateur. exécutez la méthode Remove() de l'itérateur pour supprimer des éléments, mais utilisez la méthode Remove() de ArrayList pour modifier la collection pointée par l'itérateur. Cela viole les principes de conception des itérateurs, donc une exception se produit.
L'exception signalée est la suivante :
Exception dans le fil "main" java.util.ConcurrentModificationException
à java.util.ArrayList$Itr.checkForComodification ( ArrayList.java:859)
à java.util.ArrayList$Itr.next(ArrayList.java:831)
à Text.ItaratorTest.main(ItaratorTest.java:17)
2. boucle for-each et itérateur Iterator
À partir de Java5, il existe une boucle for-each en Java, qui peut être utilisée pour parcourir des collections et des tableaux. La boucle Foreach vous permet de parcourir la collection sans conserver l'index dans une boucle for traditionnelle, ou sans appeler la méthode hasNext() dans la boucle while lors de l'utilisation de l'itérateur/ListIterator (une implémentation d'itérateur dans ArrayList). La boucle for-each simplifie le processus de parcours de n'importe quelle collection ou tableau. Mais il y a deux points à noter lors de l’utilisation d’une boucle foreach.
Les objets utilisant la boucle foreach doivent implémenter l'interface Iterable
Veuillez consulter l'exemple suivant :
import java.util.ArrayList; public class ForeachTest1 { public static void main(String args[]) { CustomCollection<String> myCollection = new CustomCollection<String>(); myCollection.add("Java"); myCollection.add("Scala"); myCollection.add("Groovy"); // What does this code will do, print language, throw exception or // compile time error for (String language : myCollection) { System.out.println(language); } } private class CustomCollection<T> { private ArrayList<T> bucket; public CustomCollection() { bucket = new ArrayList(); } public int size() { return bucket.size(); } public boolean isEmpty() { return bucket.isEmpty(); } public boolean contains(T o) { return bucket.contains(o); } public boolean add(T e) { return bucket.add(e); } public boolean remove(T o) { return bucket.remove(o); } } }
Le code ci-dessus ne sera pas compilé car la classe CustomCollection dans le code n'implémente pas l'interface Iterable
Exception dans le fil de discussion ". main" java .lang.Error : problème de compilation non résolu :
Ne peut parcourir qu'un tableau ou une instance de java.lang.Iterable
à Text.ForeachTest1.main(ForeachTest1.java:15)
En fait, il n'est pas nécessaire d'attendre la compilation pour trouver l'erreur. Eclipse affichera l'erreur dans la boucle foreach après avoir écrit ce code : Ne peut itérer que sur un tableau ou une instance de java. lang.Iterable
Ce qui peut être confirmé à nouveau à partir de l'exemple ci-dessus, c'est que la boucle foreach s'applique uniquement aux objets qui implémentent l'interface Iterable
import java.util.AbstractCollection; import java.util.ArrayList; import java.util.Iterator; public class ForeachTest { public static void main(String args[]) { CustomCollection<String> myCollection = new CustomCollection<String>(); myCollection.add("Java"); myCollection.add("Scala"); myCollection.add("Groovy"); for (String language : myCollection) { System.out.println(language); } } private static class CustomCollection<T> extends AbstractCollection<T> { private ArrayList<T> bucket; public CustomCollection() { bucket = new ArrayList(); } public int size() { return bucket.size(); } public boolean isEmpty() { return bucket.isEmpty(); } public boolean contains(Object o) { return bucket.contains(o); } public boolean add(T e) { return bucket.add(e); } public boolean remove(Object o) { return bucket.remove(o); } @Override public Iterator<T> iterator() { // TODO Auto-generated method stub return bucket.iterator(); } } }
2. L'implémentation interne de la boucle foreach s'appuie également sur Iterator
Afin de vérifier que la boucle foreach utilise Iterator. comme implémentation interne de ceci. En fait, nous utilisons toujours l'exemple au début de cet article pour vérification :
public class ItaratorTest { public static void main(String[] args) { Collection<String> list = new ArrayList<String>(); list.add("Android"); list.add("IOS"); list.add("Windows Mobile"); // example1 // Iterator<String> iterator = list.iterator(); // while (iterator.hasNext()) { // String lang = iterator.next(); // list.remove(lang); // } // example 2 for (String language : list) { list.remove(language); } } }
Exception signalée lors de l'exécution du programme :
Exception dans le fil de discussion "main" java.util.ConcurrentModificationException
à java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
à java.util.ArrayList$Itr.next( ArrayList.java:831)
at Text .ItaratorTest.main(ItaratorTest.java:22)
Cette exception montre que l'itérateur est utilisé à l'intérieur de la boucle for-each pour parcourir la collection It. appelle également Iterator.next(), qui vérifie (de l'élément) les modifications et renvoie ConcurrentModificationException.
Résumé :
Lors du parcours d'une collection, si vous souhaitez modifier la collection pendant le parcours, vous devez le faire via Iterator/listIterator, sinon des "conséquences indéterminées" peuvent survenir.
La boucle foreach est implémentée via l'itérateur. L'objet utilisant la boucle foreach doit implémenter l'interface Iterable
Ce qui précède représente l'intégralité du contenu de cet article. J'espère qu'il sera utile à l'apprentissage de chacun. J'espère également que tout le monde soutiendra le site Web PHP chinois.
Pour des articles plus détaillés sur la boucle for-each et l'itération en JAVA, veuillez faire attention au site Web PHP chinois !