Antworten:
for (Iterator<String> i = someIterable.iterator(); i.hasNext();) {
String item = i.next();
System.out.println(item);
}
Beachten Sie, dass Sie i.remove();
das for ( : )
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 (:)
Idioms array
eher ein Iterable
Objekt als ein Objekt ist, verwendet der interne Code einen int-Indexzähler und prüft array.length
stattdessen. Siehe die Java-Sprachspezifikation .
import java.util.Iterator;
undimport java.lang.Iterable;
java.util.Iterator
implementiert nicht, Iterable
so dass Sie nicht können for(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
String[] fruits = new String[] { "Orange", "Apple", "Pear", "Strawberry" };
for (String fruit : fruits) {
// fruit is an element of the `fruits` array.
}
das ist im Wesentlichen gleichbedeutend mit
for (int i = 0; i < fruits.length; i++) {
String fruit = fruits[i];
// fruit is an element of the `fruits` array.
}
Gesamtzusammenfassung:
[nsayer] Das Folgende ist die längere Form des Geschehens:
for(Iterator<String> i = someList.iterator(); i.hasNext(); ) { String item = i.next(); System.out.println(item); }
Beachten Sie, dass, wenn Sie i.remove () verwenden müssen; In Ihrer Schleife oder wenn Sie auf irgendeine Weise auf den eigentlichen Iterator zugreifen, können Sie die Redewendung for (:) nicht verwenden, da der eigentliche Iterator lediglich abgeleitet wird.
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.
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
for(int i : intList) {
System.out.println("An element in the list: " + i);
}
Iterator<Integer> intItr = intList.iterator();
while(intItr.hasNext()) {
System.out.println("An element in the list: " + intItr.next());
}
Es gibt Situationen, in denen Sie eine Iterator
direkt verwenden müssen. Wenn Sie beispielsweise versuchen, ein Element zu löschen, während Sie eine foreach
Dose verwenden (wird?), Führt dies zu a ConcurrentModificationException
.
foreach
vs for
.: Grundlegende UnterschiedeDer einzige praktische Unterschied zwischen for
und foreach
besteht darin, dass Sie bei indizierbaren Objekten keinen Zugriff auf den Index haben. Ein Beispiel, wenn die Basisschleife for
benötigt wird:
for(int i = 0; i < array.length; i++) {
if(i < 5) {
// Do something special
} else {
// Do other stuff
}
}
Obwohl Sie manuell eine separate Index-Int-Variable mit erstellen können foreach
,
int idx = -1;
for(int i : intArray) {
idx++;
...
}
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
vs for
.: LeistungWenn Sammlungen zugreifen, eine foreach
ist wesentlich schneller als die Basis for
Array - Zugriff-Schleife. Beim Zugriff auf Arrays ist der Zugriff über Indizes jedoch - zumindest bei primitiven und Wrapper-Arrays - erheblich schneller.
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
[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 358,597,622 nanoseconds
Test B: 269,167,681 nanoseconds
B faster by 89,429,941 nanoseconds (24.438799231635727% faster)
[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 377,461,823 nanoseconds
Test B: 278,694,271 nanoseconds
B faster by 98,767,552 nanoseconds (25.666236154695838% faster)
[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 288,953,495 nanoseconds
Test B: 207,050,523 nanoseconds
B faster by 81,902,972 nanoseconds (27.844689860906513% faster)
[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,373,765 nanoseconds
Test B: 283,813,875 nanoseconds
B faster by 91,559,890 nanoseconds (23.891659337194227% faster)
[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,790,818 nanoseconds
Test B: 220,770,915 nanoseconds
B faster by 155,019,903 nanoseconds (40.75164734599769% faster)
[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 326,373,762 nanoseconds
Test B: 202,555,566 nanoseconds
B faster by 123,818,196 nanoseconds (37.437545972215744% faster)
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.
Für einen List
von Integers
sind jedoch Iteratoren der klare Gewinner. Ändern Sie einfach das int-Array in der Testklasse in:
List<Integer> intList = Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100});
Und nehmen Sie die notwendigen Änderungen an der Testfunktion vor ( int[]
to List<Integer>
, length
to size()
, etc.):
[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,429,929,976 nanoseconds
Test B: 5,262,782,488 nanoseconds
A faster by 1,832,852,512 nanoseconds (34.326681820485675% faster)
[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,907,391,427 nanoseconds
Test B: 3,957,718,459 nanoseconds
A faster by 1,050,327,032 nanoseconds (26.038700083921256% faster)
[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,566,004,688 nanoseconds
Test B: 4,221,746,521 nanoseconds
A faster by 1,655,741,833 nanoseconds (38.71935684115413% faster)
[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,770,945,276 nanoseconds
Test B: 3,829,077,158 nanoseconds
A faster by 1,058,131,882 nanoseconds (27.134122749113843% faster)
[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,467,474,055 nanoseconds
Test B: 5,183,149,104 nanoseconds
A faster by 1,715,675,049 nanoseconds (32.60101667104192% faster)
[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,439,983,933 nanoseconds
Test B: 3,509,530,312 nanoseconds
A faster by 69,546,379 nanoseconds (1.4816434912159906% faster)
[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,451,101,466 nanoseconds
Test B: 5,057,979,210 nanoseconds
A faster by 1,606,877,744 nanoseconds (31.269164666060377% faster)
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:
Weitere Informationen: Was ist effizienter, eine für jede Schleife oder ein Iterator?
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 :
import java.text.NumberFormat;
import java.util.Locale;
/**
<P>{@code java TimeIteratorVsIndexIntArray 1000000}</P>
@see <CODE><A HREF="/programming/180158/how-do-i-time-a-methods-execution-in-java">/programming/180158/how-do-i-time-a-methods-execution-in-java</A></CODE>
**/
public class TimeIteratorVsIndexIntArray {
public static final NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
public static final void main(String[] tryCount_inParamIdx0) {
int testCount;
// Get try-count from a command-line parameter
try {
testCount = Integer.parseInt(tryCount_inParamIdx0[0]);
}
catch(ArrayIndexOutOfBoundsException | NumberFormatException x) {
throw new IllegalArgumentException("Missing or invalid command line parameter: The number of testCount for each test. " + x);
}
//Test proper...START
int[] intArray = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100};
long lStart = System.nanoTime();
for(int i = 0; i < testCount; i++) {
testIterator(intArray);
}
long lADuration = outputGetNanoDuration("A", lStart);
lStart = System.nanoTime();
for(int i = 0; i < testCount; i++) {
testFor(intArray);
}
long lBDuration = outputGetNanoDuration("B", lStart);
outputGetABTestNanoDifference(lADuration, lBDuration, "A", "B");
}
private static final void testIterator(int[] int_array) {
int total = 0;
for(int i = 0; i < int_array.length; i++) {
total += int_array[i];
}
}
private static final void testFor(int[] int_array) {
int total = 0;
for(int i : int_array) {
total += i;
}
}
//Test proper...END
//Timer testing utilities...START
public static final long outputGetNanoDuration(String s_testName, long l_nanoStart) {
long lDuration = System.nanoTime() - l_nanoStart;
System.out.println("Test " + s_testName + ": " + nf.format(lDuration) + " nanoseconds");
return lDuration;
}
public static final long outputGetABTestNanoDifference(long l_aDuration, long l_bDuration, String s_aTestName, String s_bTestName) {
long lDiff = -1;
double dPct = -1.0;
String sFaster = null;
if(l_aDuration > l_bDuration) {
lDiff = l_aDuration - l_bDuration;
dPct = 100.00 - (l_bDuration * 100.0 / l_aDuration + 0.5);
sFaster = "B";
}
else {
lDiff = l_bDuration - l_aDuration;
dPct = 100.00 - (l_aDuration * 100.0 / l_bDuration + 0.5);
sFaster = "A";
}
System.out.println(sFaster + " faster by " + nf.format(lDiff) + " nanoseconds (" + dPct + "% faster)");
return lDiff;
}
//Timer testing utilities...END
}
for(int value : int_array) {/* loop content */}
in Ihrem Test am langsamsten ist, weil es syntaktisch äquivalent zu for(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:
char[] grades = ....
for(int i = 0; i < grades.length; i++) { // for i goes from 0 to grades.length
System.out.print(grades[i]); // Print grades[i]
}
Die foreach-Syntax ermöglicht es, dieses allgemeine Muster natürlicher und weniger syntaktisch verrauscht zu schreiben.
for(char grade : grades) { // foreach grade in grades
System.out.print(grade); // print that grade
}
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.
In Java 8-Funktionen können Sie Folgendes verwenden:
List<String> messages = Arrays.asList("First", "Second", "Third");
void forTest(){
messages.forEach(System.out::println);
}
First
Second
Third
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.
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:
List<String> someList = new ArrayList<String>();
someList.add("Apple");
someList.add("Ball");
for (String item : someList) {
System.out.println(item);
}
// IS TRANSLATED TO:
for(Iterator<String> stringIterator = someList.iterator(); stringIterator.hasNext(); ) {
String item = stringIterator.next();
System.out.println(item);
}
Wenn der Ausdruck notwendigerweise einen Array-Typ hat, T[]
dann:
String[] someArray = new String[2];
someArray[0] = "Apple";
someArray[1] = "Ball";
for(String item2 : someArray) {
System.out.println(item2);
}
// IS TRANSLATED TO:
for (int i = 0; i < someArray.length; i++) {
String item2 = someArray[i];
System.out.println(item2);
}
Java 8 hat Streams eingeführt, die im Allgemeinen eine bessere Leistung erzielen. Wir können sie verwenden als:
someList.stream().forEach(System.out::println);
Arrays.stream(someArray).forEach(System.out::println);
Eine foreach-Schleifensyntax lautet:
for (type obj:array) {...}
Beispiel:
String[] s = {"Java", "Coffe", "Is", "Cool"};
for (String str:s /*s is the array*/) {
System.out.println(str);
}
Ausgabe:
Java
Coffe
Is
Cool
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.
for (double b:s) // Invalid-double is not String
Wenn Sie Elemente bearbeiten möchten, verwenden Sie die ursprüngliche for
Schleife wie folgt:
for (int i = 0; i < s.length-1 /*-1 because of the 0 index */; i++) {
if (i==1) //1 because once again I say the 0 index
s[i]="2 is cool";
else
s[i] = "hello";
}
Wenn wir nun s auf die Konsole werfen, erhalten wir:
hello
2 is cool
hello
hello
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 die Collection<T>
Schnittstelle erweitert wird Iterable<T>
.
Das in Wikipedia erwähnte Konzept einer foreach-Schleife wird nachfolgend hervorgehoben:
Im Gegensatz zu anderen for-Schleifenkonstrukten behalten foreach-Schleifen jedoch normalerweise keinen expliziten Zähler bei : Sie sagen im Wesentlichen "mache dies mit allem in dieser Menge" und nicht "mache dies x-mal". Dies vermeidet mögliche Fehler nacheinander und vereinfacht das Lesen von Code.
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.
// In this loop it is assumed that the list starts with index 0
for(int i=0; i<list.length; i++){
}
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.
In Java 8 wurde forEach eingeführt. Mit dieser Liste können Karten geloopt werden.
Schleife eine Liste mit jedem
List<String> someList = new ArrayList<String>();
someList.add("A");
someList.add("B");
someList.add("C");
someList.forEach(listItem -> System.out.println(listItem))
oder
someList.forEach(listItem-> {
System.out.println(listItem);
});
Schleife eine Karte mit jedem
Map<String, String> mapList = new HashMap<>();
mapList.put("Key1", "Value1");
mapList.put("Key2", "Value2");
mapList.put("Key3", "Value3");
mapList.forEach((key,value)->System.out.println("Key: " + key + " Value : " + value));
oder
mapList.forEach((key,value)->{
System.out.println("Key : " + key + " Value : " + value);
});
for (Iterator<String> itr = someList.iterator(); itr.hasNext(); ) {
String item = itr.next();
System.out.println(item);
}
Wenn Sie ältere Java-Versionen verwenden Java 7
, können Sie die foreach
Schleife wie folgt verwenden.
List<String> items = new ArrayList<>();
items.add("A");
items.add("B");
items.add("C");
items.add("D");
items.add("E");
for(String item : items){
System.out.println(item);
}
Im Folgenden finden Sie die neueste Methode zur Verwendung von foreach
Loop-InJava 8
(Schleife einer Liste mit forEach
+ Lambda-Ausdruck oder Methodenreferenz)
//lambda
//Output : A,B,C,D,E
items.forEach(item->System.out.println(item));
//method reference
//Output : A,B,C,D,E
items.forEach(System.out::println);
Weitere Informationen finden Sie unter diesem Link.
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.
removeIf
könnte die Verwendung von das richtige Werkzeug sein
Eine Alternative zu forEach, um Ihr "für jeden" zu vermeiden:
List<String> someList = new ArrayList<String>();
Variante 1 (glatt):
someList.stream().forEach(listItem -> {
System.out.println(listItem);
});
Variante 2 (parallele Ausführung (schneller)):
someList.parallelStream().forEach(listItem -> {
System.out.println(listItem);
});
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:
void cancelAll(Collection<TimerTask> list) {
for (Iterator<TimerTask> i = list.iterator(); i.hasNext();)
i.next().cancel();
}
Verwenden für jeden:
void cancelAll(Collection<TimerTask> list) {
for (TimerTask t : list)
t.cancel();
}
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 ".
for (TimerTask t : list)
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).
Vor Java 8 müssen Sie Folgendes verwenden:
Iterator<String> iterator = someList.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
}
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:
someList.stream().forEach(System.out::println);
Weitere Informationen zu Streams finden Sie hier .
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.
for (Iterator<String> i = someList.iterator(); i.hasNext(); )
System.out.println(i.next());
In der Sun-Dokumentation finden Sie jeweils eine gute Beschreibung .
Wie so viele gute Antworten sagten, muss ein Objekt das implementieren, Iterable interface
wenn es eine for-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:
public class ForEachTest {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("111");
list.add("222");
for (String str : list) {
System.out.println(str);
}
}
}
Wenn wir javap
dann diese Klasse dekompilieren, erhalten wir dieses Bytecode-Beispiel:
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: new #16 // class java/util/ArrayList
3: dup
4: invokespecial #18 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: ldc #19 // String 111
11: invokeinterface #21, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
16: pop
17: aload_1
18: ldc #27 // String 222
20: invokeinterface #21, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
25: pop
26: aload_1
27: invokeinterface #29, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
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 eines Iterator
zur Kompilierungszeit. Dies kann erklären, warum ein Objekt, das das nicht implementiert Iterable interface
, ein löst , Exception
wenn es versucht, die for-each
Schleife zu verwenden.
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
int [] intArray = {1, 3, 5, 7, 9};
for(int currentValue : intArray) {
System.out.println(currentValue);
}
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:
1
3
5
7
9
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.
String [] myStrings = {
"alpha",
"beta",
"gamma",
"delta"
};
for(String currentString : myStrings) {
System.out.println(currentString);
}
Ausgabe:
alpha
beta
gamma
delta
Beispiel - Liste
Die erweiterte for-Schleife kann auch verwendet werden, um eine java.util.List wie folgt zu durchlaufen:
List<String> myList = new ArrayList<String>();
myList.add("alpha");
myList.add("beta");
myList.add("gamma");
myList.add("delta");
for(String currentItem : myList) {
System.out.println(currentItem);
}
Die Schleifendeklaration lautet: Schleife über myList Liste der Zeichenfolgen und speichere den aktuellen Listenwert in der Variablen currentItem.
Ausgabe:
alpha
beta
gamma
delta
Beispiel - Set
Die erweiterte for-Schleife kann auch verwendet werden, um eine java.util.Set wie folgt zu durchlaufen:
Set<String> mySet = new HashSet<String>();
mySet.add("alpha");
mySet.add("alpha");
mySet.add("beta");
mySet.add("gamma");
mySet.add("gamma");
mySet.add("delta");
for(String currentItem : mySet) {
System.out.println(currentItem);
}
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:
alpha
delta
beta
gamma
public static Boolean Add_Tag(int totalsize)
{ List<String> fullst = new ArrayList<String>();
for(int k=0;k<totalsize;k++)
{
fullst.addAll();
}
}
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.
Wie viele andere Antworten richtig angeben, for
each
loop
ist der Zucker nur syntaktisch über dieselbe alte for
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 aus
javac -XD-printflat -d src/ MyFile.java
//-d is used to specify the directory for output java file
Um diese Frage zu beantworten, habe ich eine Datei erstellt und zwei Versionen von geschrieben for
each
, eine mit array
und eine mit a list
. Meine java
Datei sah so aus.
import java.util.*;
public class Temp{
private static void forEachArray(){
int[] arr = new int[]{1,2,3,4,5};
for(int i: arr){
System.out.print(i);
}
}
private static void forEachList(){
List<Integer> list = Arrays.asList(1,2,3,4,5);
for(Integer i: list){
System.out.print(i);
}
}
}
Wenn ich compiled
diese Datei mit dem obigen Schalter habe, habe ich die folgende Ausgabe erhalten.
import java.util.*;
public class Temp {
public Temp() {
super();
}
private static void forEachArray() {
int[] arr = new int[]{1, 2, 3, 4, 5};
for (/*synthetic*/ int[] arr$ = arr, len$ = arr$.length, i$ = 0; i$ < len$; ++i$) {
int i = arr$[i$];
{
System.out.print(i);
}
}
}
private static void forEachList() {
List list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5)});
for (/*synthetic*/ Iterator i$ = list.iterator(); i$.hasNext(); ) {
Integer i = (Integer)i$.next();
{
System.out.print(i);
}
}
}
}
Sie können sehen, dass zusammen mit dem anderen syntaktischen Zucker (Autoboxing) für jede Schleife in einfache Schleifen geändert wurde.
List<Item> Items = obj.getItems();
for(Item item:Items)
{
System.out.println(item);
}
Iteriert über alle Objekte in der Elementtabelle.