Zunächst gibt es zwei Arten von for-Schleifen, die sich sehr unterschiedlich verhalten. Man verwendet Indizes:
for (int i = 0; i < list.size(); i++) {
Thing t = list.get(i);
...
}
Diese Art von Schleife ist nicht immer möglich. Listen haben beispielsweise Indizes, Sets jedoch nicht, da es sich um ungeordnete Sammlungen handelt.
Die andere, die foreach-Schleife, verwendet einen Iterator hinter den Kulissen:
for (Thing thing : list) {
...
}
Dies funktioniert mit jeder Art von Iterable-Sammlung (oder Array)
Und schließlich können Sie einen Iterator verwenden, der auch mit jedem Iterable funktioniert:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
...
}
Sie haben also tatsächlich 3 Schleifen zum Vergleichen.
Sie können sie in verschiedenen Begriffen vergleichen: Leistung, Lesbarkeit, Fehleranfälligkeit, Fähigkeit.
Ein Iterator kann Dinge tun, die eine foreach-Schleife nicht kann. Beispielsweise können Sie Elemente während der Iteration entfernen, wenn der Iterator dies unterstützt:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
if (shouldBeDeleted(thing) {
it.remove();
}
}
Listen bieten auch Iteratoren, die in beide Richtungen iterieren können. Eine foreach-Schleife iteriert nur vom Anfang bis zum Ende.
Ein Iterator ist jedoch gefährlicher und weniger lesbar. Wenn Sie nur eine foreach-Schleife benötigen, ist dies die am besten lesbare Lösung. Mit einem Iterator könnten Sie Folgendes tun, was ein Fehler wäre:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
System.out.println(it.next().getFoo());
System.out.println(it.next().getBar());
}
Eine foreach-Schleife lässt einen solchen Fehler nicht zu.
Die Verwendung von Indizes für den Zugriff auf Elemente ist bei Sammlungen, die von einem Array unterstützt werden, etwas effizienter. Wenn Sie jedoch Ihre Meinung ändern und eine LinkedList anstelle einer ArrayList verwenden, ist die Leistung plötzlich schrecklich, da list.get(i)
die verknüpfte Liste bei jedem Zugriff alle ihre Elemente bis zur i-ten durchlaufen muss. Ein Iterator (und damit die foreach-Schleife) hat dieses Problem nicht. Es wird immer die bestmögliche Methode zum Durchlaufen von Elementen der angegebenen Sammlung verwendet, da die Sammlung selbst über eine eigene Iterator-Implementierung verfügt.
Meine allgemeine Faustregel lautet: Verwenden Sie die foreach-Schleife, es sei denn, Sie benötigen wirklich die Funktionen eines Iterators. Ich würde for-Schleife nur mit Indizes mit Arrays verwenden, wenn ich Zugriff auf den Index innerhalb der Schleife benötige.