Wenn der Index nur im Weg ist
Eine gezählte for-Schleife gibt dir einen Zähler, eine Bedingung und einen Aktualisierungsschritt. Aber sehr oft interessiert dich die Position eines Elements gar nicht – du willst einfach mit jedem etwas tun, der Reihe nach, von Anfang bis Ende. Dafür einen Index zu verwalten ist überflüssige Arbeit, und genau dort schleichen sich Off-by-one-Fehler ein.
Die for-each-Schleife (Java nennt sie das erweiterte for) lässt den Zähler komplett weg. Du benennst eine Variable, richtest sie auf eine Collection, und die Schleife reicht dir jedes Element der Reihe nach.
Grundlegende Syntax
Die Form lautet for (Typ element : collection). Lies den Doppelpunkt als das Wort „in":
Kein i, kein scores.length, kein scores[i]. Bei jedem Durchlauf ist score das nächste Element. Die Schleife läuft einmal pro Element und stoppt automatisch, wenn keines mehr da ist – du kannst weder über das Ende hinauslaufen noch ein Element zu früh beginnen.
Über eine Liste iterieren
Dieselbe Schleife funktioniert mit allem Iterierbaren, was List, Set und die übrigen Collection-Typen einschließt. Der Elementtyp steht vor dem Variablennamen:
Beachte, dass du nicht wissen oder dich kümmern musstest, ob langs von einem Array, einer verketteten Liste oder etwas anderem gestützt wird – for-each funktioniert bei allen gleich. Das ist seine eigentliche Stärke: eine lesbare Syntax für jede Collection.
var erspart dir den Typnamen
Wenn der Elementtyp lang oder offensichtlich ist, lässt var den Compiler ihn ableiten, damit du dich nicht wiederholst:
Ohne var wäre diese Schleifenvariable der Zungenbrecher Map.Entry<String, Integer>. var hält das lesbar, und der Typ wird zur Kompilierzeit weiterhin vollständig geprüft – das ist kein lockerer, dynamischer Typ.
Der Modifikations-Fallstrick
Hier ist die Regel, über die jeder stolpert: Du kannst zu einer Collection nichts hinzufügen oder daraus entfernen, während eine for-each-Schleife sie durchläuft. Tust du es doch, wirft sie eine ConcurrentModificationException:
List<String> items = new ArrayList<>(List.of("a", "b", "c"));
for (String item : items) {
if (item.equals("b")) {
items.remove(item); // wirft ConcurrentModificationException
}
}
Die Schleife merkt, dass sich die Liste unter ihr verändert hat, und bricht ab, statt Elemente still zu überspringen oder zu wiederholen. Um sicher zu entfernen, steig auf einen expliziten Iterator herab, der ein remove() besitzt, von dem die Schleife weiß:
Eine gängige Abkürzung ist items.removeIf(item -> item.equals("b")), das dasselbe in einer Zeile erledigt.
Nur lesen, nicht neu zuweisen
Eine weitere subtile Grenze: Der Schleifenvariable etwas zuzuweisen ändert nur die lokale Kopie, nicht die Collection. Das überrascht alle, die aus Sprachen kommen, in denen die Schleifenvariable eine lebendige Referenz ist:
Wenn du ins Array zurückschreiben musst, brauchst du den Index – und das bedeutet die klassische gezählte for-Schleife: for (int i = 0; i < nums.length; i++) nums[i] = nums[i] * 10;. Bei Objekt-Elementen kannst du das Objekt, auf das die Variable zeigt, verändern (etwa einen Setter aufrufen), aber du kannst es nicht in der Collection ersetzen.
break und continue funktionieren weiterhin
Ein for-each ist eine echte Schleife, also verhalten sich break und continue genauso wie überall sonst – break verlässt die Schleife, continue springt zum nächsten Element:
Das gibt keep und dann keep aus – es überspringt "skip" und hält bei "stop", bevor es "never" erreicht. Du bist also nicht gezwungen, jedes Element zu besuchen; du gibst nur den Index gegen saubereren Code auf.
Als Nächstes: Arrays
Du hast jetzt mehrmals über Arrays iteriert, ohne dich damit aufzuhalten, was sie eigentlich sind – indexierte Container fester Größe mit diesem .length-Feld. Die nächste Seite geht zurück zum Anfang und behandelt Arrays ordentlich: wie man sie deklariert, mit welchen Standardwerten sie beginnen und worin sich ihre feste Größe von einer wachsenden ArrayList unterscheidet.
Häufig gestellte Fragen
Was ist eine for-each-Schleife in Java?
Eine for-each-Schleife (auch erweitertes for genannt) durchläuft jedes Element eines Arrays oder einer Collection ohne Zähler: for (Typ element : collection) { ... }. Lies sie als „für jedes Element in der Collection". Sie ist sauberer als eine gezählte for-Schleife, wenn du nur jedes Element brauchst und nie den Index.
Was ist der Unterschied zwischen einer for-Schleife und einer for-each-Schleife in Java?
Die klassische for-Schleife nutzt einen expliziten Zähler (for (int i = 0; i < arr.length; i++)), du kontrollierst also Index und Richtung. Die for-each-Schleife, for (Typ x : arr), hat keinen Index – sie besucht jedes Element der Reihe nach. Nimm for-each für rein lesende Durchläufe von vorne nach hinten; nimm die gezählte Schleife, wenn du den Index brauchst, Elemente überspringen oder die Struktur der Collection ändern willst.
Warum wirft meine for-each-Schleife eine ConcurrentModificationException?
Weil du add() oder remove() auf der Collection aufgerufen hast, während du sie mit einem for-each iteriert hast. Die Schleife erkennt die strukturelle Änderung und wirft die Ausnahme, um dich vor undefiniertem Verhalten zu schützen. Um Elemente sicher zu entfernen, nutze einen expliziten Iterator und dessen remove()-Methode oder sammle die zu löschenden Elemente und entferne sie nach der Schleife.