Als relativ neuer Benutzer der Java-Sprache versuche ich mich mit all den Möglichkeiten (oder zumindest den nicht pathologischen) vertraut zu machen, wie man durch eine Liste (oder vielleicht andere Sammlungen) iterieren kann, und welche Vor- und Nachteile jede Methode hat.
Gegeben ein List list
Objekt, kenne ich die folgenden Möglichkeiten, um durch alle Elemente zu iterieren:
Grundlegende for Schleife (natürlich gibt es auch entsprechende while
/ do while
Schleifen)
// Nicht empfohlen (siehe unten)!
for (int i = 0; i < list.size(); i++) {
E element = list.get(i);
// 1 - Methoden des Elements aufrufen
// 2 - 'i' verwenden, um indexbasierte Aufrufe von Methoden der Liste zu machen
// ...
}
Anmerkung: Wie @amarseillan bemerkt hat, ist diese Form keine gute Wahl für die Iteration über List
s, da die tatsächliche Implementierung der get
Methode möglicherweise nicht so effizient ist wie bei Verwendung eines Iterator
. Zum Beispiel müssen LinkedList-Implementierungen alle Elemente vor i durchlaufen, um das i-te Element zu erhalten.
In obigem Beispiel gibt es für die Listenimplementierung keine Möglichkeit, "ihre Position zu speichern", um zukünftige Iterationen effizienter zu machen. Für ein ArrayList ist das nicht wirklich wichtig, weil die Komplexität / Kosten von get
konstant sind (O(1)), während sie für ein LinkedList proportional zur Größe der Liste sind (O(n)).
Für weitere Informationen über die Rechenkomplexität der integrierten Collections
-Implementierungen, schauen Sie sich diese Frage an.
Verbesserte for Schleife (gut erklärt in dieser Frage)
for (E element : list) {
// 1 - Methoden des Elements aufrufen
// ...
}
Iterator
for (Iterator iter = list.iterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - Methoden des Elements aufrufen
// 2 - iter.remove() verwenden, um das aktuelle Element aus der Liste zu entfernen
// ...
}
ListIterator
for (ListIterator iter = list.listIterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - Methoden des Elements aufrufen
// 2 - iter.remove() verwenden, um das aktuelle Element aus der Liste zu entfernen
// 3 - iter.add(...) verwenden, um ein neues Element in die Liste einzufügen
// zwischen element und iter->next()
// 4 - iter.set(...) verwenden, um das aktuelle Element zu ersetzen
// ...
}
Funktionales Java
list.stream().map(e -> e + 1); // Kann eine Transformationsfunktion für e anwenden
Iterable.forEach, Stream.forEach, ...
(Eine map-Methode aus der Stream-API von Java 8 (siehe Antwort von @i_am_zero).)
In Java 8 haben Sammlungsklassen, die Iterable
implementieren (zum Beispiel alle List
s), nun eine forEach
Methode, die anstelle der oben gezeigten for-Schleife verwendet werden kann. (Hier ist eine andere Frage, die einen guten Vergleich liefert.)
Arrays.asList(1,2,3,4).forEach(System.out::println);
// 1 - Methoden eines Elements aufrufen
// 2 - wäre ein Verweis auf das enthaltende Objekt erforderlich, um ein Element zu entfernen
// (TODO: Bitte jemand bestätigen / verneinen)
// 3 - trennt funktional die Iteration von der Aktion ab,
// die mit jedem Element ausgeführt wird.
Arrays.asList(1,2,3,4).stream().forEach(System.out::println);
// Gleiche Möglichkeiten wie oben plus möglicherweise höhere
// Nutzung von Parallelität
// (Vorsicht: Als Konsequenz ist die Ausführungsreihenfolge nicht garantiert,
// siehe [Stream.forEachOrdered][stream-foreach-ordered] für weitere
// Informationen dazu).
Gibt es noch andere Möglichkeiten, wenn ja, welche?
(Übrigens, mein Interesse resultiert überhaupt nicht aus dem Wunsch, die Leistung zu optimieren; ich möchte nur wissen, welche Formen mir als Entwickler zur Verfügung stehen.)