Erwägen:
List<String> someList = new ArrayList<String>();
// add "monkey", "donkey", "skeleton key" to someList
for (String item : someList) {
System.out.println(item);
}
Wie würde die äquivalente for
Schleife aussehen, ohne die für jede Syntax zu verwenden?
java
foreach
syntactic-sugar
Jay R.
quelle
quelle
Antworten:
Beachten Sie, dass Sie
i.remove();
dasfor ( : )
Idiom nicht verwenden können , wenn Sie es in Ihrer Schleife verwenden oder auf irgendeine Weise auf den tatsächlichen Iterator zugreifen müssen , da der tatsächliche Iterator lediglich abgeleitet wird.Wie von Denis Bueno festgestellt, funktioniert dieser Code für jedes Objekt, das die
Iterable
Schnittstelle implementiert .Wenn die rechte Seite des
for (:)
Idiomsarray
eher einIterable
Objekt als ein Objekt ist, verwendet der interne Code einen int-Indexzähler und prüftarray.length
stattdessen. Siehe die Java-Sprachspezifikation .quelle
import java.util.Iterator;
undimport java.lang.Iterable;
java.util.Iterator
implementiert nicht,Iterable
so dass Sie nicht könnenfor(String s : (Iterator<String>)foo)
. Ich verstehe, warum das so ist, aber es ist irritierend.Das Konstrukt für jedes gilt auch für Arrays. z.B
das ist im Wesentlichen gleichbedeutend mit
Gesamtzusammenfassung:
[nsayer] Das Folgende ist die längere Form des Geschehens:
[Denis Bueno]
quelle
Die in Java 5 hinzugefügte
foreach
Schleife (auch als "Enhanced for Loop" bezeichnet) entspricht der Verwendung des syntaktischen Zuckers von --it für dasselbe. Daher sollte beim Lesen jedes Elements nacheinander und in der Reihenfolge a immer über einem Iterator ausgewählt werden, da dies bequemer und prägnanter ist.java.util.Iterator
foreach
für jedes
Iterator
Es gibt Situationen, in denen Sie eine
Iterator
direkt verwenden müssen. Wenn Sie beispielsweise versuchen, ein Element zu löschen, während Sie eineforeach
Dose verwenden (wird?), Führt dies zu aConcurrentModificationException
.foreach
vsfor
.: Grundlegende UnterschiedeDer einzige praktische Unterschied zwischen
for
undforeach
besteht darin, dass Sie bei indizierbaren Objekten keinen Zugriff auf den Index haben. Ein Beispiel, wenn die Basisschleifefor
benötigt wird:Obwohl Sie manuell eine separate Index-Int-Variable mit erstellen können
foreach
,Dies wird nicht empfohlen, da der variable Bereich nicht ideal ist und die Basisschleife
for
einfach das Standard- und erwartete Format für diesen Anwendungsfall ist.foreach
vsfor
.: LeistungWenn Sammlungen zugreifen, eine
foreach
ist wesentlich schneller als die Basisfor
Array - Zugriff-Schleife. Beim Zugriff auf Arrays ist der Zugriff über Indizes jedoch - zumindest bei primitiven und Wrapper-Arrays - erheblich schneller.Timing des Unterschieds zwischen Iterator- und Indexzugriff für primitive Int-Arrays
Indizes sind beim Zugriff oder bei Arrays 23 bis 40 Prozent schneller als Iteratoren . Hier ist die Ausgabe der Testklasse am Ende dieses Beitrags, die die Zahlen in einem 100-Elemente-Primitive-Int-Array summiert (A ist Iterator, B ist Index):
int
Integer
Ich habe dies auch für ein
Integer
Array ausgeführt, und Indizes sind immer noch der klare Gewinner, aber nur zwischen 18 und 25 Prozent schneller.Bei Sammlungen sind Iteratoren schneller als Indizes
Für einen
List
vonIntegers
sind jedoch Iteratoren der klare Gewinner. Ändern Sie einfach das int-Array in der Testklasse in:Und nehmen Sie die notwendigen Änderungen an der Testfunktion vor (
int[]
toList<Integer>
,length
tosize()
, etc.):In einem Test sind sie fast gleichwertig, aber mit Sammlungen gewinnt der Iterator.
* Dieser Beitrag basiert auf zwei Antworten, die ich auf Stack Overflow geschrieben habe:
Verwendung und Syntax für jede Schleife in Java
Sollte ich einen Iterator oder einen Forloop zum Iterieren verwenden?
Weitere Informationen: Was ist effizienter, eine für jede Schleife oder ein Iterator?
Die vollständige Testklasse
Ich habe diese Klasse zum Vergleichen der Zeit erstellt, die benötigt wird, um zwei Dinge zu erledigen, nachdem ich diese Frage zu Stack Overflow gelesen habe :
quelle
for(int value : int_array) {/* loop content */}
in Ihrem Test am langsamsten ist, weil es syntaktisch äquivalent zufor(int i = 0; i < int_array.length; i++) {int value = int_array[i]; /* loop content */}
dem ist, was Ihr Test nicht vergleicht.int value = int_array[i];
zu Beginn ihres Tests einen Test durchführen Schleife, dann könnten sie auch foreach verwenden. Es sei denn, sie benötigen aus irgendeinem Grund auch Zugriff auf den Index. Kurz gesagt, alles hängt vom Kontext ab.)Hier ist eine Antwort, die keine Kenntnisse über Java-Iteratoren voraussetzt. Es ist weniger genau, aber es ist nützlich für die Bildung.
Während der Programmierung schreiben wir oft Code, der wie folgt aussieht:
Die foreach-Syntax ermöglicht es, dieses allgemeine Muster natürlicher und weniger syntaktisch verrauscht zu schreiben.
Darüber hinaus gilt diese Syntax für Objekte wie Listen oder Sets, die keine Array-Indizierung unterstützen, aber die Java Iterable-Schnittstelle implementieren.
quelle
Die for-each-Schleife in Java verwendet den zugrunde liegenden Iteratormechanismus. Es ist also identisch mit dem Folgenden:
quelle
In Java 8-Funktionen können Sie Folgendes verwenden:
Ausgabe
quelle
Dies wird durch die Antwort von nsayer impliziert, aber es ist erwähnenswert, dass die OP-Syntax für (..) funktioniert, wenn "someList" etwas ist , das java.lang.Iterable implementiert - es muss keine Liste oder eine Sammlung von sein java.util. Daher können mit dieser Syntax auch Ihre eigenen Typen verwendet werden.
quelle
Wie in JLS für jede Schleife definiert, kann es zwei Formen geben:
Wenn der Ausdruckstyp ein Subtyp von
Iterable
ist, lautet die Übersetzung wie folgt:Wenn der Ausdruck notwendigerweise einen Array-Typ hat,
T[]
dann:Java 8 hat Streams eingeführt, die im Allgemeinen eine bessere Leistung erzielen. Wir können sie verwenden als:
quelle
Eine foreach-Schleifensyntax lautet:
Beispiel:
Ausgabe:
WARNUNG: Sie können mit der foreach-Schleife auf Array-Elemente zugreifen, diese jedoch NICHT initialisieren. Verwenden Sie dazu die Originalschleife
for
.WARNUNG: Sie müssen den Typ des Arrays mit dem anderen Objekt abgleichen.
Wenn Sie Elemente bearbeiten möchten, verwenden Sie die ursprüngliche
for
Schleife wie folgt:Wenn wir nun s auf die Konsole werfen, erhalten wir:
quelle
Das Java-Schleifenkonstrukt "for-each" ermöglicht die Iteration über zwei Objekttypen:
T[]
(Arrays jeglicher Art)java.lang.Iterable<T>
Die
Iterable<T>
Schnittstelle hat nur eine Methode :Iterator<T> iterator()
. Dies funktioniert bei Objekten vom Typ,Collection<T>
da dieCollection<T>
Schnittstelle erweitert wirdIterable<T>
.quelle
Das in Wikipedia erwähnte Konzept einer foreach-Schleife wird nachfolgend hervorgehoben:
Das Konzept einer foreach-Schleife beschreibt also, dass die Schleife keinen expliziten Zähler verwendet, was bedeutet, dass keine Indizes zum Durchlaufen der Liste verwendet werden müssen, wodurch der Benutzer vor einem Fehler nach dem anderen geschützt wird. Um das allgemeine Konzept dieses Off-by-One-Fehlers zu beschreiben, nehmen wir ein Beispiel einer Schleife, die mithilfe von Indizes in einer Liste durchlaufen wird.
Angenommen, die Liste beginnt mit Index 1, dann löst diese Schleife eine Ausnahme aus, da bei Index 0 kein Element gefunden wird und dieser Fehler als Fehler "Off-by-One" bezeichnet wird. Um diesen Fehler zu vermeiden, wird das Konzept einer foreach-Schleife verwendet. Es mag auch andere Vorteile geben, aber ich denke, dies ist das Hauptkonzept und der Vorteil der Verwendung einer foreach-Schleife.
quelle
In Java 8 wurde forEach eingeführt. Mit dieser Liste können Karten geloopt werden.
Schleife eine Liste mit jedem
oder
Schleife eine Karte mit jedem
oder
quelle
quelle
Wenn Sie ältere Java-Versionen verwenden
Java 7
, können Sie dieforeach
Schleife wie folgt verwenden.Im Folgenden finden Sie die neueste Methode zur Verwendung von
foreach
Loop-InJava 8
(Schleife einer Liste mit
forEach
+ Lambda-Ausdruck oder Methodenreferenz)Weitere Informationen finden Sie unter diesem Link.
https://www.mkyong.com/java8/java-8-foreach-examples/
quelle
Hier ist ein äquivalenter Ausdruck.
quelle
Beachten Sie auch, dass die Verwendung der "foreach" -Methode in der ursprünglichen Frage einige Einschränkungen aufweist, z. B., dass Elemente während der Iteration nicht aus der Liste entfernt werden können.
Die neue for-Schleife ist einfacher zu lesen und macht einen separaten Iterator überflüssig, kann jedoch nur in schreibgeschützten Iterationsdurchläufen verwendet werden.
quelle
removeIf
könnte die Verwendung von das richtige Werkzeug seinEine Alternative zu forEach, um Ihr "für jeden" zu vermeiden:
Variante 1 (glatt):
Variante 2 (parallele Ausführung (schneller)):
quelle
for(
Formular gerne, wenn ich sicherstellen möchte, dass der gleiche Thread verwendet wird. Ich verwende gerne das Stream-Formular, wenn ich die Multithread-Ausführung zulassen möchte.Es verleiht Ihrem Code Schönheit, indem es alle grundlegenden Schleifen-Unordnung beseitigt. Es gibt Ihrem Code ein sauberes Aussehen, das unten begründet ist.
Normale
for
Schleife:Verwenden für jeden:
for-each ist ein Konstrukt über einer Sammlung, die Iterator implementiert . Denken Sie daran, dass Ihre Sammlung Iterator implementieren sollte . Andernfalls können Sie es nicht für jeden verwenden.
Die folgende Zeile lautet " für jede TimerTask t in Liste ".
Bei jedem Fall ist die Wahrscheinlichkeit von Fehlern geringer. Sie müssen sich nicht darum kümmern, den Iterator oder den Schleifenzähler zu initialisieren und zu beenden (wo Fehler auftreten können).
quelle
Vor Java 8 müssen Sie Folgendes verwenden:
Mit der Einführung von Streams in Java 8 können Sie jedoch dasselbe mit viel weniger Syntax tun. Zum Beispiel können
someList
Sie Folgendes tun:Weitere Informationen zu Streams finden Sie hier .
quelle
The foreach loop, added in Java 5 (also called the "enhanced for loop"), is equivalent to using a java.util.Iterator
Es würde ungefähr so aussehen. Sehr mürrisch.
In der Sun-Dokumentation finden Sie jeweils eine gute Beschreibung .
quelle
Wie so viele gute Antworten sagten, muss ein Objekt das implementieren,
Iterable interface
wenn es einefor-each
Schleife verwenden möchte .Ich werde ein einfaches Beispiel posten und versuchen, auf andere Weise zu erklären, wie eine
for-each
Schleife funktioniert.Das
for-each
Schleifenbeispiel:Wenn wir
javap
dann diese Klasse dekompilieren, erhalten wir dieses Bytecode-Beispiel:Wie wir in der letzten Zeile des Beispiels sehen können, konvertiert der Compiler die Verwendung des
for-each
Schlüsselworts automatisch in die Verwendung einesIterator
zur Kompilierungszeit. Dies kann erklären, warum ein Objekt, das das nicht implementiertIterable interface
, ein löst ,Exception
wenn es versucht, diefor-each
Schleife zu verwenden.quelle
Das Java für jede Schleife (auch als erweiterte for-Schleife bezeichnet) ist eine vereinfachte Version einer for-Schleife. Der Vorteil ist, dass weniger Code geschrieben und weniger Variablen verwaltet werden müssen. Der Nachteil ist, dass Sie keine Kontrolle über den Schrittwert und keinen Zugriff auf den Schleifenindex innerhalb des Schleifenkörpers haben.
Sie werden am besten verwendet, wenn der Schrittwert ein einfaches Inkrement von 1 ist und Sie nur Zugriff auf das aktuelle Schleifenelement benötigen. Zum Beispiel, wenn Sie jedes Element in einem Array oder einer Sammlung durchlaufen müssen, ohne vor oder hinter das aktuelle Element zu schauen.
Es gibt keine Schleifeninitialisierung, keine boolesche Bedingung und der Schrittwert ist implizit und ein einfaches Inkrement. Aus diesem Grund werden sie für Schleifen als viel einfacher als normal angesehen.
Erweiterte for-Schleifen folgen dieser Ausführungsreihenfolge:
1) Schleifenkörper
2) Wiederholen Sie den Vorgang ab Schritt 1, bis das gesamte Array oder die gesamte Sammlung durchlaufen wurde
Beispiel - Integer Array
Die Variable currentValue enthält den aktuellen Wert, der im Array intArray durchlaufen wird. Beachten Sie, dass es keinen expliziten Schrittwert gibt - es ist immer ein Inkrement um 1.
Man kann sich vorstellen, dass der Doppelpunkt „in“ bedeutet. Die erweiterte for-Schleifendeklaration lautet also: Schleife über intArray und speichere den aktuellen Array-Int-Wert in der Variablen currentValue.
Ausgabe:
Beispiel - String Array
Wir können die for-each-Schleife verwenden, um über ein Array von Zeichenfolgen zu iterieren. Die Schleifendeklaration lautet: Schleife über das Array myStrings String und speichere den aktuellen String-Wert in der Variablen currentString.
Ausgabe:
Beispiel - Liste
Die erweiterte for-Schleife kann auch verwendet werden, um eine java.util.List wie folgt zu durchlaufen:
Die Schleifendeklaration lautet: Schleife über myList Liste der Zeichenfolgen und speichere den aktuellen Listenwert in der Variablen currentItem.
Ausgabe:
Beispiel - Set
Die erweiterte for-Schleife kann auch verwendet werden, um eine java.util.Set wie folgt zu durchlaufen:
Die Schleifendeklaration lautet: Schleife über mySet Set of Strings und speichere den aktuellen Set-Wert in der currentItem-Variablen. Beachten Sie, dass doppelte String-Werte nicht gespeichert werden, da dies ein Set ist.
Ausgabe:
Quelle: Schleifen in Java - Ultimate Guide
quelle
quelle
Das Java für jedes Idiom kann nur auf Arrays oder Objekte vom Typ * Iterable angewendet werden . Diese Redewendung ist implizit, da sie wirklich von einem Iterator unterstützt wird. Der Iterator wird vom Programmierer programmiert und verwendet häufig einen ganzzahligen Index oder einen Knoten (abhängig von der Datenstruktur), um seine Position zu verfolgen. Auf dem Papier ist es langsamer als eine reguläre for-Schleife, zumindest für "lineare" Strukturen wie Arrays und Listen, aber es bietet eine größere Abstraktion.
quelle
Das sieht verrückt aus, aber hey, es funktioniert
Das funktioniert. Magie
quelle
Wie viele andere Antworten richtig angeben,
for
each
loop
ist der Zucker nur syntaktisch über dieselbe altefor
loop
und der Compiler übersetzt ihn in dieselbe alte for-Schleife.javac (open jdk) hat einen Schalter
-XD-printflat
, der eine Java-Datei generiert, in der der gesamte syntaktische Zucker entfernt ist. Der vollständige Befehl sieht folgendermaßen ausEntfernen wir also den syntaktischen Zucker
Um diese Frage zu beantworten, habe ich eine Datei erstellt und zwei Versionen von geschrieben
for
each
, eine mitarray
und eine mit alist
. Meinejava
Datei sah so aus.Wenn ich
compiled
diese Datei mit dem obigen Schalter habe, habe ich die folgende Ausgabe erhalten.Sie können sehen, dass zusammen mit dem anderen syntaktischen Zucker (Autoboxing) für jede Schleife in einfache Schleifen geändert wurde.
quelle
Iteriert über alle Objekte in der Elementtabelle.
quelle