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 HashSet
ist mit dieser Einschränkung nicht allein. Darüber hinaus HashSet
gibt 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 name
handelt es sich um den Namen der Sammlungsvariablen, Type
um den Typ der Elemente der Sammlung, iterator()
um eine der Methoden der Sammlung und it
um den Namen der Iteratorvariablen.
Ein Iteratorobjekt verfügt über drei Methoden:
Methode | Beschreibung |
---|---|
|
Gibt das nächste Element in der Sammlung zurück |
|
Prüft, ob es Elemente gibt, die noch nicht durchlaufen wurden |
|
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 |
---|---|
|
Erstellen Sie ein HashSet Objekt, das Elemente speichert String . Wir fügen der Variablen Begrüßungen in verschiedenen Sprachen hinzu set . Holen Sie sich ein Iteratorobjekt für die set Menge. Solange noch Elemente vorhanden sind. Holen Sie sich das nächste Element. Zeigen Sie das Element auf dem Bildschirm an |
3. For-each
Schleife
Der Hauptnachteil eines Iterators besteht darin, dass Ihr Code umständlicher wird als die Verwendung einer for
Schleife.
Zum Vergleich zeigen wir eine Liste mit einer for
Schleife und auch mit einem Iterator an:
Iterator | for-Schleife |
---|---|
|
|
Ja, es ist viel besser, die Elemente einer ArrayList
Schleife 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 collection
ist der Name der Sammlungsvariablen, Type
der Typ der Elemente in der Sammlung und name
der 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 |
---|---|
|
|
Wenn der Compiler auf eine for-each
Schleife 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-each
Schleife und verwenden sie fast immer, wenn sie alle Elemente einer Sammlung durchlaufen müssen.
Sogar das Durchlaufen einer ArrayList
Liste mithilfe einer for-each
Schleife sieht kürzer aus:
For-each-Schleife | for-Schleife |
---|---|
|
|
4. Entfernen eines Elements in einer for-each
Schleife
Die for-each
Schleife hat einen Nachteil: Sie kann Elemente nicht korrekt entfernen. Wenn Sie Code wie diesen schreiben, erhalten Sie eine Fehlermeldung.
Code | Notiz |
---|---|
|
Der Entfernungsvorgang erzeugt einen Fehler! |
Das ist ein sehr schöner und verständlicher Code, aber er wird nicht funktionieren.
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 collection
können Sie eine gewöhnliche Schleife mit einer i
Zählervariablen verwenden.
Code |
---|
|
Diese Option ist jedoch nicht für HashSet
und HashMap
Sammlungen 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 |
---|---|
|
|
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-each
Schleife verwenden und Elemente aus der ursprünglichen Sammlung löschen.
Code | Notiz |
---|---|
|
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.
GO TO FULL VERSION