1. Iterator-Iterator
Schnittstelle: Iterator
public interface Iterator<E>{ boolean hasNext(); E next(); void remove(); }
Wenn Sie sich die Iterator-Schnittstellen-API ansehen, können Sie erkennen, dass es sich um einen Iterator zum Iterieren der Sammlung handelt. Iteratoren ermöglichen es dem Aufrufer, mithilfe einer genau definierten Semantik Elemente aus der Sammlung zu entfernen, auf die der Iterator während der Iteration zeigt.
Besonders hervorzuheben ist die Verwendung der Methode „remove()“ dieses Iterators: Entfernt das letzte vom Iterator zurückgegebene Element (optionale Operation) aus der Sammlung, auf die der Iterator zeigt. Diese Methode kann nur einmal pro Aufruf von next aufgerufen werden. Wenn die Sammlung, auf die der Iterator zeigt, während einer Iteration anders als durch den Aufruf dieser Methode (Remove-Methode) geändert wird, ist das Verhalten des Iterators undefiniert. Der Schnittstellendesigner hat beim Entwerfen der 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 } } }
Dieser Code löst bei der Ausführung eine ConcurrentModificationException-Ausnahme aus, da wir nicht die Methode „remove()“ des Iterators verwenden, um Elemente während der Ausführung des Iterators zu löschen, sondern Verwenden Sie die Methode „remove()“ von ArrayList, um die Sammlung zu ändern, auf die der Iterator zeigt. Dies verstößt gegen die Designprinzipien von Iteratoren, sodass eine Ausnahme auftritt.
Die gemeldete Ausnahme lautet wie folgt:
Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) at java.util.ArrayList$Itr.next(ArrayList.java:831) at Text.ItaratorTest.main(ItaratorTest.java:17)
2. for-each-Schleife und Iterator-Iterator
Ab Java5 gibt es in Java die every-Schleife kann zum Durchlaufen von Sammlungen und Arrays verwendet werden. Mit der Foreach-Schleife können Sie über die Sammlung iterieren, ohne den Index in einer herkömmlichen for-Schleife beizubehalten oder ohne die Methode hasNext() in der while-Schleife aufzurufen, wenn Sie iterator / ListIterator (eine Iteratorimplementierung in ArrayList) verwenden. Die for-each-Schleife vereinfacht das Durchlaufen einer Sammlung oder eines Arrays. Bei der Verwendung einer foreach-Schleife sind jedoch zwei Punkte zu beachten.
Objekte, die eine foreach-Schleife verwenden, müssen die Iterable
Bitte sehen Sie sich das folgende Beispiel an:
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); } } }
Der obige Code wird nicht kompiliert, da die CustomCollection-Klasse in Der Code implementiert die Iterable
Exception in thread "main" java.lang.Error: Unresolved compilation problem: Can only iterate over an array or an instance of java.lang.Iterable at Text.ForeachTest1.main(ForeachTest1.java:15)
Tatsächlich muss nicht bis zur Kompilierung gewartet werden, um den Fehler zu finden. Eclipse wird dies tun Beim Schreiben dieses Codes wird in der foreach-Schleife ein Fehler angezeigt: Kann nur über ein Array oder eine Instanz von java.lang.Iterable iterieren
Aus dem obigen Beispiel kann noch einmal bestätigt werden, dass die foreach-Schleife nur für gilt das 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. Die interne Implementierung der foreach-Schleife basiert ebenfalls auf Iterator
Um die Tatsache zu überprüfen, dass die foreach-Schleife Iterator als interne Implementierung verwendet , wir verwenden immer noch diesen Artikel Die erste Instanz zur Überprüfung:
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); } } }
Ausnahme gemeldet, wenn das Programm ausgeführt wird:
Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) at java.util.ArrayList$Itr.next(ArrayList.java:831) at Text.ItaratorTest.main(ItaratorTest.java:22)
Diese Ausnahme zeigt, dass ein Iterator innerhalb des For- verwendet wird. Außerdem wird jede Schleife zum Durchlaufen der Sammlung aufgerufen, die nach Änderungen sucht und eine ConcurrentModificationException auslöst.
Zusammenfassung:
Wenn Sie beim Durchlaufen einer Sammlung die Sammlung während des Durchlaufens ändern möchten, müssen Sie dies über Iterator/listIterator tun, da sonst „unbestimmte Konsequenzen“ auftreten können.
Die foreach-Schleife wird durch einen Iterator implementiert. Das Objekt, das die foreach-Schleife verwendet, muss die Iterable-Schnittstelle implementieren