1. Hintergrund zur Entstehung von Iteratoren

Sie kennen sich bereits aus HashSet. Wenn Sie sich wirklich damit beschäftigt haben und nicht nur eine Lektion gelesen haben, hätten Sie diese Frage stellen sollen:

Wie zeige ich eine Liste aller HashSet-Elemente auf dem Bildschirm an? Schließlich hat die Schnittstelle keine get()Methoden set()!

Und HashSetist mit dieser Einschränkung nicht allein. Darüber hinaus HashSetgibt es viele andere Sammlungen, die das Abrufen von Elementen per Index nicht zulassen, da die Elemente keine definierte Reihenfolge haben.

Im Laufe der Jahre haben Programmierer viele komplexe Datenstrukturen wie Diagramme und Bäume erfunden. Oder Listen von Listen.

Viele Container ändern die Reihenfolge ihrer Elemente, wenn neue Elemente hinzugefügt oder vorhandene Elemente entfernt werden. Beispielsweise speichert eine Liste Elemente in einer bestimmten Reihenfolge, und wenn ein neues Element hinzugefügt wird, wird es fast immer in der Mitte der Liste eingefügt.

Und es kommt auch zu Situationen, in denen es einen Container gibt, der Elemente speichert, jedoch nicht in einer festen Reihenfolge.

Nehmen wir nun an, wir möchten alle Elemente aus einer solchen Sammlung in ein Array oder eine Liste kopieren. Wir müssen alle Elemente besorgen. Die Reihenfolge, in der wir die Elemente durchlaufen, ist uns egal – wichtig ist, dass wir dieselben Elemente nicht mehr als einmal durchlaufen. Wie machen wir das?


2. Iterator für eine Sammlung

Als Lösung für das obige Problem wurden Iteratoren vorgeschlagen.

Ein Iterator ist ein spezielles Objekt, das einer Sammlung zugeordnet ist und dabei hilft, alle Elemente der Sammlung zu durchlaufen, ohne sie zu wiederholen.

Sie können den folgenden Code verwenden, um einen Iterator für jede Sammlung abzurufen:

Iterator<Type> it = name.iterator();

Dabei namehandelt es sich um den Namen der Sammlungsvariablen, Typeum den Typ der Elemente der Sammlung, iterator()um eine der Methoden der Sammlung und itum den Namen der Iteratorvariablen.

Ein Iteratorobjekt verfügt über drei Methoden:

Methode Beschreibung
Type next()
Gibt das nächste Element in der Sammlung zurück
boolean hasNext()
Prüft, ob es Elemente gibt, die noch nicht durchlaufen wurden
void remove()
Entfernt das aktuelle Element der Sammlung

Diese Methoden ähneln in gewisser Weise den Scanner-Klassen nextInt)und hasNextInt()-Methoden.

Die next()Methode gibt das nächste Element der Sammlung zurück, aus der wir den Iterator erhalten haben.

Die hasNext()Methode prüft, ob die Sammlung zusätzliche Elemente enthält, die der Iterator noch nicht zurückgegeben hat.

So zeigen Sie alle Elemente eines an HashSet:

Code Anmerkungen
HashSet<String> set = new HashSet<String>();

set.add("Hallo");
set.add("Hello");
set.add("Hola");
set.add("Bonjour");
set.add("Ciao");
set.add("Namaste");

Iterator<String> it = set.iterator();
while (it.hasNext())
{
   String str = it.next();
   System.out.println(str);
}
Erstellen Sie ein HashSetObjekt, das Elemente speichert String.


Wir fügen der Variablen Begrüßungen in verschiedenen Sprachen hinzu set.




Holen Sie sich ein Iteratorobjekt für die setMenge.
Solange noch Elemente vorhanden sind.

Holen Sie sich das nächste Element.
Zeigen Sie das Element auf dem Bildschirm an


3. For-eachSchleife

Der Hauptnachteil eines Iterators besteht darin, dass Ihr Code umständlicher wird als die Verwendung einer forSchleife.

Zum Vergleich zeigen wir eine Liste mit einer forSchleife und auch mit einem Iterator an:

Iterator for-Schleife
ArrayList<String> list = new ArrayList<String>();

Iterator<String> it = list.iterator();
while (it.hasNext())
{
   String str = it.next();
   System.out.println(str);
}
ArrayList<String> list = new ArrayList<String>();

for (int i = 0; i < list.size(); i++)
{
   String str = list.get(i);
   System.out.println(str);
}

Ja, es ist viel besser, die Elemente einer ArrayListSchleife zu durchlaufen – alles wird kürzer.

Aber die Macher von Java haben sich erneut dazu entschieden, uns etwas Zucker über den Kopf zu streuen. Zu unserem Glück war es syntaktischer Zucker .

Sie gaben Java eine neue Art von Schleife und nannten sie Schleife for-each. So sieht es im Allgemeinen aus:

for(Type name:collection)

Dabei collectionist der Name der Sammlungsvariablen, Typeder Typ der Elemente in der Sammlung und nameder Name einer Variablen, die bei jeder Iteration der Schleife den nächsten Wert aus der Sammlung übernimmt.

Diese Art von Schleife durchläuft mithilfe eines impliziten Iterators alle Elemente einer Sammlung. So funktioniert es tatsächlich:

For-each-Schleife Was der Compiler sieht: Schleife mit einem Iterator
ArrayList<String> list = new ArrayList<String>();

for (String str: list)
{
   System.out.println(str);
}
ArrayList<String> list = new ArrayList<String>();
Iterator<String> it = list.iterator();

while (it.hasNext())
{
   String str = it.next();
   System.out.println(str);
}

Wenn der Compiler auf eine for-eachSchleife in Ihrem Code stößt, ersetzt er diese einfach durch den Code auf der rechten Seite: Er fügt einen Aufruf zum Abrufen eines Iterators zusammen mit allen anderen fehlenden Methodenaufrufen hinzu.

Programmierer lieben die for-eachSchleife und verwenden sie fast immer, wenn sie alle Elemente einer Sammlung durchlaufen müssen.

Sogar das Durchlaufen einer ArrayListListe mithilfe einer for-eachSchleife sieht kürzer aus:

For-each-Schleife for-Schleife
ArrayList<String> list = new ArrayList<String>();

for (String str: list)
{
   System.out.println(str);
}
ArrayList<String> list = new ArrayList<String>();

for (int i = 0; i < list.size(); i++)
{
   String str = list.get(i);
   System.out.println(str);
}


4. Entfernen eines Elements in einer for-eachSchleife

Die for-eachSchleife hat einen Nachteil: Sie kann Elemente nicht korrekt entfernen. Wenn Sie Code wie diesen schreiben, erhalten Sie eine Fehlermeldung.

Code Notiz
ArrayList<String> list = new ArrayList<String>();

list.add("Hallo");
list.add("Hello");
list.add("Hola");
list.add("Bonjour");
list.add("Ciao");
list.add("Namaste");

for (String str: list)
{
   if (str.equals("Hello"))
      list.remove(str);
}












Der Entfernungsvorgang erzeugt einen Fehler!

Das ist ein sehr schöner und verständlicher Code, aber er wird nicht funktionieren.

Wichtig!

Sie können eine Sammlung nicht ändern, während Sie sie mit einem Iterator durchlaufen.

Es gibt drei Möglichkeiten, diese Einschränkung zu umgehen.

1. Verwenden Sie eine andere Art von Schleife

When traversing an ArrayList collectionkönnen Sie eine gewöhnliche Schleife mit einer iZählervariablen verwenden.

Code
for (int i = 0; i < list.size(); i++)
{
   String str = list.get(i);

   if (str.equals("Hello"))
   {
      list.remove(str);
      i--; // We need to decrease i, because the remove operation shifted the elements
   }
}

Diese Option ist jedoch nicht für HashSetund HashMapSammlungen geeignet

2. Verwenden Sie einen expliziten Iterator

Sie können einen Iterator explizit verwenden und seine remove()Methode aufrufen.

Version, die funktioniert Version, die nicht funktioniert
Iterator<String> it = set.iterator();
while (it.hasNext())
{
   String str = it.next();
   if (str.equals("Hello"))
       it.remove();
}

for (String str: list) { if (str.equals("Hello")) list.remove(str); }

remove()Beachten Sie, dass wir die Methode für das Iteratorobjekt aufrufen ! Der Iterator ist sich bewusst, dass das Element entfernt wurde und kann die Situation richtig handhaben.

3. Verwenden Sie eine Kopie der Sammlung

Sie können auch eine Kopie der Sammlung erstellen und die Kopie dann in einer for-eachSchleife verwenden und Elemente aus der ursprünglichen Sammlung löschen.

Code Notiz
ArrayList<String> listCopy = new ArrayList(list);

for (String str: listCopy)
{
   if (str.equals("Hello"))
      list.remove(str);
}
Das Erstellen einer Kopie einer Sammlung ist super einfach.



Die Schleife verwendet den Iterator für die Kopie der Sammlung.
Elemente werden aus der Sammlung entfernt list.

Die Sammlung wird relativ schnell kopiert, da die Elemente selbst nicht dupliziert werden. Stattdessen speichert die neue Sammlung Verweise auf die Elemente, die bereits in der alten Sammlung vorhanden sind.