Come funziona il ciclo Java "per ogni"?


1499

Prendere in considerazione:

List<String> someList = new ArrayList<String>();
// add "monkey", "donkey", "skeleton key" to someList
for (String item : someList) {
    System.out.println(item);
}

Come sarebbe il forloop equivalente senza usare il per ogni sintassi?


Risposte:


1176
for (Iterator<String> i = someIterable.iterator(); i.hasNext();) {
    String item = i.next();
    System.out.println(item);
}

Si noti che se è necessario utilizzare i.remove();nel proprio ciclo o accedere in qualche modo all'iteratore reale, non è possibile utilizzare l' for ( : )idioma, poiché l'iteratore effettivo viene semplicemente dedotto.

Come notato da Denis Bueno, questo codice funziona per qualsiasi oggetto che implementa l' Iterableinterfaccia .

Inoltre, se il lato destro del for (:)linguaggio è arrayun Iterableoggetto anziché un oggetto, il codice interno utilizza un contatore di indici int e verifica array.lengthinvece. Vedi le specifiche del linguaggio Java .


14
Ho trovato solo chiamando un ciclo while come while (someList.hasMoreElements ()) {// do qualcosa}} - mi avvicina alla grazia del codice che speravo di trovare quando ho cercato questa domanda.
James T Snell,

6
Vedi anche docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html che spiega il ciclo foreach (quando è stato introdotto)
PhoneixS,

1
per gli sviluppatori Android Studio: import java.util.Iterator;eimport java.lang.Iterable;
dsdsdsdsd,

Frustrantemente, java.util.Iteratornon si implementa Iterablequindi non puoi for(String s : (Iterator<String>)foo). Capisco perché questo è, ma è irritante.
Christopher Schultz,

499

Il costrutto per ciascuno è valido anche per gli array. per esempio

String[] fruits = new String[] { "Orange", "Apple", "Pear", "Strawberry" };

for (String fruit : fruits) {
    // fruit is an element of the `fruits` array.
}

che è essenzialmente equivalente a

for (int i = 0; i < fruits.length; i++) {
    String fruit = fruits[i];
    // fruit is an element of the `fruits` array.
}

Quindi, riepilogo generale:
[nsayer] Quanto segue è la forma più lunga di ciò che sta accadendo:

for(Iterator<String> i = someList.iterator(); i.hasNext(); ) {
  String item = i.next();
  System.out.println(item);
}

Nota che se devi usare i.remove (); nel tuo ciclo, o accedi all'iteratore vero e proprio in qualche modo, non puoi usare l'idioma for (:), dato che l'Iteratore reale è semplicemente inferito.

[Denis Bueno]

È implicito nella risposta di nsayer, ma vale la pena notare che la sintassi del PO per (..) funzionerà quando "someList" è qualcosa che implementa java.lang.Iterable - non deve essere un elenco o una raccolta da java.util. Anche i tuoi tipi, quindi, possono essere usati con questa sintassi.


161

Il foreachloop , aggiunto in Java 5 (chiamato anche "Enhanced for loop"), equivale a usare java.util.Iteratorlo zucchero sintattico di --it per la stessa cosa. Pertanto, quando si legge ogni elemento, uno per uno e in ordine, a foreachdeve sempre essere scelto su un iteratore, poiché è più conveniente e conciso.

per ciascuno

for(int i : intList) {
   System.out.println("An element in the list: " + i);
}

Iterator

Iterator<Integer> intItr = intList.iterator();
while(intItr.hasNext()) {
   System.out.println("An element in the list: " + intItr.next());
}

Ci sono situazioni in cui è necessario utilizzare Iteratordirettamente un . Ad esempio, il tentativo di eliminare un elemento mentre si utilizza un comando foreachcan (will?) In a ConcurrentModificationException.

foreachvs for.: differenze di base

L'unica differenza pratica tra fore foreachè che, nel caso di oggetti indicizzabili, non si ha accesso all'indice. Un esempio quando forè richiesto il loop di base :

for(int i = 0; i < array.length; i++) {
   if(i < 5) {
      // Do something special
   }  else {
      // Do other stuff
   }
}

Sebbene sia possibile creare manualmente un indice int-variabile separato con foreach,

int idx = -1;
for(int i : intArray) {
   idx++;
   ...
}

non è raccomandato, poiché l' ambito variabile non è l'ideale e il forciclo di base è semplicemente il formato standard e previsto per questo caso d'uso.

foreachvs for.: Performance

Quando si accede alle raccolte, a foreachè significativamente più velocefor dell'accesso alla matrice del ciclo di base . Quando si accede agli array, tuttavia - almeno con array primitivi e wrapper - l'accesso tramite indici è notevolmente più veloce.

Temporizzazione della differenza tra iteratore e accesso all'indice per int-array primitivi

Gli indici sono 23- 40 per cento più veloce di iteratori durante l'accesso into Integerarray. Ecco l'output della classe testing in fondo a questo post, che somma i numeri in una matrice di primitive-int di 100 elementi (A è iteratore, B è indice):

[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)

Ho anche eseguito questo per un Integerarray e gli indici sono ancora il chiaro vincitore, ma solo tra il 18 e il 25 percento più veloci.

Per le raccolte, gli iteratori sono più veloci degli indici

Per un Listof Integers, tuttavia, gli iteratori sono il chiaro vincitore. Basta cambiare int-array nella classe test 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});

E apporta le modifiche necessarie alla funzione test ( int[]a List<Integer>, lengtha size(), ecc.):

[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 un test sono quasi equivalenti, ma con le raccolte vince l'iteratore.

* Questo post si basa su due risposte che ho scritto su Stack Overflow:

Qualche informazione in più: qual è più efficiente, un ciclo for-each o un iteratore?

La classe di test completa

Ho creato questa classe di confronto-il-tempo-che-fa-fare-due-cose dopo aver letto questa domanda su StackTranslate.it:

import  java.text.NumberFormat;
import  java.util.Locale;

/**
   &lt;P&gt;{@code java TimeIteratorVsIndexIntArray 1000000}&lt;/P&gt;

   @see  &lt;CODE&gt;&lt;A HREF=&quot;/programming/180158/how-do-i-time-a-methods-execution-in-java&quot;&gt;/programming/180158/how-do-i-time-a-methods-execution-in-java&lt;/A&gt;&lt;/CODE&gt;
 **/
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

}

4
Questa risposta è ora un post sul blog ed è stata creata da due risposte correlate che ho scritto: qui e qui . Include anche una classe genericamente utile per confrontare la velocità di due funzioni (in basso).
aliteralmind

1
Solo un piccolo commento qui, non dovresti dichiarare categoricamente che per (:) la sintassi è sempre meglio per accedere alle raccolte; se si utilizza un elenco di array, il ciclo for (:) sarà circa 2 volte più lento rispetto a quando si utilizza for (int i = 0, len = arrayList.size (); i <len; i ++). Penso che tu l'abbia menzionato nel link [link] ( stackoverflow.com/questions/2113216/… ), ma è importante sottolineare che ...
Leone,

@Leo È un buon punto. Un ArrayList è Collection, ma è supportato da un array, motivo per cui il normale per è migliore per questo.
aliteralmind,

Immagino che for(int value : int_array) {/* loop content */}sia il più lento nel tuo test perché è sintatticamente equivalente a for(int i = 0; i < int_array.length; i++) {int value = int_array[i]; /* loop content */}, che non è quello che confronta il tuo test.
daiscog,

(a proposito, non sto dicendo che il tuo test non è valido, ma potrebbe valere la pena notare i motivi alla base della differenza in modo che le persone possano scegliere ciò che è giusto per il loro particolare scenario. Se stanno facendo un int value = int_array[i];all'inizio del loro per , quindi potrebbero anche usare foreach. A meno che non abbiano bisogno dell'accesso all'indice per qualche motivo. In breve, tutto dipende dal contesto.)
daiscog

129

Ecco una risposta che non presuppone la conoscenza di Iteratori Java. È meno preciso, ma è utile per l'educazione.

Durante la programmazione scriviamo spesso un codice simile al seguente:

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]
}

La sintassi foreach consente a questo modello comune di essere scritto in un modo più naturale e meno sintatticamente rumoroso.

for(char grade : grades) {   // foreach grade in grades
    System.out.print(grade); // print that grade
}

Inoltre, questa sintassi è valida per oggetti come Elenchi o Set che non supportano l'indicizzazione dell'array, ma che implementano l'interfaccia Java Iterable.


40

Il ciclo for-each in Java utilizza il meccanismo iteratore sottostante. Quindi è identico al seguente:

Iterator<String> iterator = someList.iterator();

while (iterator.hasNext()) {
  String item = iterator.next();
  System.out.println(item);
}

25

Nelle funzionalità di Java 8 è possibile utilizzare questo:

List<String> messages = Arrays.asList("First", "Second", "Third");

void forTest(){
    messages.forEach(System.out::println);
}

Produzione

First
Second
Third

7
queste informazioni casuali non rispondono nemmeno in remoto alla domanda
Tim

25

È implicito nella risposta di nsayer, ma vale la pena notare che la sintassi del PO per (..) funzionerà quando "someList" è qualcosa che implementa java.lang.Iterable - non deve essere un elenco o una raccolta da java.util. Anche i tuoi tipi, quindi, possono essere usati con questa sintassi.


1
fd ha ragione - il codice interno quando il lato destro di for (:) idioma usa int e array.length invece di recuperare un Iteratore. forums.sun.com/thread.jspa?messageID=2743233
nsayer

24

Come definito in JLS per ogni ciclo può avere due forme:

  1. Se il tipo di espressione è un sottotipo di Iterableallora la traduzione è come:

    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);
    }
  2. Se l'espressione ha necessariamente un tipo di array, T[]allora:

    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 ha introdotto flussi che funzionano generalmente meglio. Possiamo usarli come:

someList.stream().forEach(System.out::println);
Arrays.stream(someArray).forEach(System.out::println);

2
La risposta più pertinente e accurata. Enchansed for ha davvero due traduzioni.
Zarial,

23

Una sintassi del ciclo foreach è:

for (type obj:array) {...}

Esempio:

String[] s = {"Java", "Coffe", "Is", "Cool"};
for (String str:s /*s is the array*/) {
    System.out.println(str);
}

Produzione:

Java
Coffe
Is
Cool

ATTENZIONE: è possibile accedere agli elementi dell'array con il ciclo foreach, ma NON è possibile inizializzarli. Usa il forloop originale per quello.

ATTENZIONE: è necessario abbinare il tipo di array con l'altro oggetto.

for (double b:s) // Invalid-double is not String

Se vuoi modificare elementi, usa il forciclo originale in questo modo:

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";
}

Ora se scarichiamo s sulla console, otteniamo:

hello
2 is cool
hello
hello

21

Il costrutto del ciclo Java "per ogni" consentirà l'iterazione su due tipi di oggetti:

  • T[] (array di qualsiasi tipo)
  • java.lang.Iterable<T>

L' Iterable<T>interfaccia ha un solo metodo: Iterator<T> iterator(). Funziona su oggetti di tipo Collection<T>perché l' Collection<T>interfaccia si estende Iterable<T>.


16

Il concetto di un ciclo foreach come menzionato in Wikipedia è evidenziato di seguito:

A differenza di altri costrutti di loop, tuttavia, i loop foreach di solito non mantengono alcun contatore esplicito : essenzialmente dicono "fai questo a tutto in questo set", piuttosto che "fai questo x volte". Questo evita potenziali errori off-by-one e semplifica la lettura del codice.

Quindi il concetto di un ciclo foreach descrive che il ciclo non utilizza alcun contatore esplicito, il che significa che non è necessario utilizzare gli indici per attraversare l'elenco, salvando così l'utente dall'errore off-by-one. Per descrivere il concetto generale di questo errore off-by-one, prendiamo un esempio di un ciclo da attraversare in un elenco usando gli indici.

// In this loop it is assumed that the list starts with index 0
for(int i=0; i<list.length; i++){

}

Ma supponiamo che se l'elenco inizia con l'indice 1, questo ciclo genererà un'eccezione in quanto non troverà alcun elemento nell'indice 0 e questo errore viene chiamato un errore off-by-one. Quindi, per evitare questo errore off-by-one, viene utilizzato il concetto di un ciclo foreach. Potrebbero esserci anche altri vantaggi, ma questo è quello che penso sia il concetto principale e il vantaggio di usare un ciclo foreach.


13

In Java 8, hanno introdotto per ciascuno. Usandolo Elenco, Maps può essere ripetuto in loop.

Ripeti un elenco usando per ciascuno

List<String> someList = new ArrayList<String>();
someList.add("A");
someList.add("B");
someList.add("C");

someList.forEach(listItem -> System.out.println(listItem))

o

someList.forEach(listItem-> {
     System.out.println(listItem); 
});

Eseguire il ciclo di una mappa usando per ciascuno

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));

o

mapList.forEach((key,value)->{
    System.out.println("Key : " + key + " Value : " + value);
});

12
for (Iterator<String> itr = someList.iterator(); itr.hasNext(); ) {
   String item = itr.next();
   System.out.println(item);
}

11

Utilizzando versioni precedenti di Java, incluso il loop, Java 7puoi usare il foreachloop come segue.

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);
        }

Di seguito è riportato il modo più recente di utilizzare il foreachloop inJava 8

(esegui il ciclo di un elenco con forEachespressione + lambda o riferimento al metodo)

//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);

Per maggiori informazioni consultare questo link.

https://www.mkyong.com/java8/java-8-foreach-examples/


10

Ecco un'espressione equivalente.

for(Iterator<String> sit = someList.iterator(); sit.hasNext(); ) {
    System.out.println(sit.next());
}

10

Si noti inoltre che l'utilizzo del metodo "foreach" nella domanda originale presenta alcune limitazioni, come l'impossibilità di rimuovere elementi dall'elenco durante l'iterazione.

Il nuovo for-loop è più facile da leggere ed elimina la necessità di un iteratore separato, ma è davvero utilizzabile solo in passaggi di iterazione di sola lettura.


1
In quei casi, l'uso di removeIfpotrebbe essere lo strumento giusto
ncmathsadist,

9

Un'alternativa a forEach per evitare il tuo "per ciascuno":

List<String> someList = new ArrayList<String>();

Variante 1 (semplice):

someList.stream().forEach(listItem -> {
    System.out.println(listItem);
});

Variante 2 (esecuzione parallela (più veloce)):

someList.parallelStream().forEach(listItem -> {
    System.out.println(listItem);
});

2
Avrei dovuto menzionare che è stato aggiunto in Java 1.8
TheLibrarian il

Non possiamo essere sicuri al 100% che venga utilizzato lo stesso thread. Mi piace utilizzare il for(modulo se mi piace assicurarmi che venga utilizzato lo stesso thread. Mi piace usare lo stream-form se mi piace consentire l'esecuzione multithread.
Grim

8

Aggiunge bellezza al tuo codice rimuovendo tutto il disordine di loop di base. Dà un aspetto pulito al tuo codice, giustificato di seguito.

forAnello normale :

void cancelAll(Collection<TimerTask> list) {
    for (Iterator<TimerTask> i = list.iterator(); i.hasNext();)
         i.next().cancel();
}

Usando per-ciascuno:

void cancelAll(Collection<TimerTask> list) {
    for (TimerTask t : list)
        t.cancel();
}

for-each è un costrutto su una raccolta che implementa Iterator . Ricorda che la tua raccolta dovrebbe implementare Iterator ; altrimenti non puoi usarlo con for-each.

La seguente riga viene letta come " per ogni TimerTask t in list " .

for (TimerTask t : list)

Ci sono meno possibilità di errori in caso di for-each. Non devi preoccuparti di inizializzare l'iteratore o inizializzare il contatore di loop e terminarlo (dove c'è spazio per errori).


8

Prima di Java 8, è necessario utilizzare quanto segue:

Iterator<String> iterator = someList.iterator();

while (iterator.hasNext()) {
    String item = iterator.next();
    System.out.println(item);
}

Tuttavia, con l'introduzione di Streams in Java 8 puoi fare la stessa cosa con molta meno sintassi. Ad esempio, per someListte puoi fare:

someList.stream().forEach(System.out::println);

Puoi trovare ulteriori informazioni sui flussi qui .


The foreach loop, added in Java 5 (also called the "enhanced for loop"), is equivalent to using a java.util.Iterator
Alex78191

7

Sembrerebbe qualcosa del genere. Molto croccante.

for (Iterator<String> i = someList.iterator(); i.hasNext(); )
        System.out.println(i.next());

C'è una buona writeup su per ogni nella documentazione Sun .


6

Come hanno detto tante buone risposte, un oggetto deve implementare Iterable interfacese vuole usare un for-eachciclo.

Pubblicherò un semplice esempio e proverò a spiegare in modo diverso come funziona un for-eachciclo.

L' for-eachesempio del ciclo:

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);
        }
    }
}

Quindi, se usiamo javapper decompilare questa classe, otterremo questo esempio di bytecode:

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;

Come possiamo vedere dall'ultima riga dell'esempio, il compilatore convertirà automaticamente l'uso della for-eachparola chiave nell'uso di un Iteratoral momento della compilazione. Questo potrebbe spiegare perché l'oggetto, che non implementa il Iterable interface, lancerà un Exceptionquando tenta di usare il for-eachciclo.


6

Il Java per ogni loop (aka migliorato per anello) è una versione semplificata di un ciclo for. Il vantaggio è che c'è meno codice da scrivere e meno variabili da gestire. Il rovescio della medaglia è che non hai alcun controllo sul valore del passo e nessun accesso all'indice del loop all'interno del corpo del loop.

Sono meglio utilizzati quando il valore del passo è un semplice incremento di 1 e quando è necessario solo l'accesso all'elemento loop corrente. Ad esempio, se è necessario eseguire il ciclo su ogni elemento in un array o in una raccolta senza sbirciare avanti o indietro l'elemento corrente.

Non c'è inizializzazione del ciclo, nessuna condizione booleana e il valore del passo è implicito ed è un semplice incremento. Questo è il motivo per cui sono considerati molto più semplici del normale per i loop.

I miglioramenti per i loop seguono questo ordine di esecuzione:

1) corpo del loop

2) ripetere dal passaggio 1 fino a quando non è stata attraversata l'intera matrice o raccolta

Esempio: matrice di numeri interi

int [] intArray = {1, 3, 5, 7, 9};
for(int currentValue : intArray) {
  System.out.println(currentValue);
}

La variabile currentValue contiene il valore corrente in fase di loop nell'array intArray. Si noti che non esiste un valore di passaggio esplicito: è sempre un incremento di 1.

Si può pensare che il colon significhi "in". Pertanto, la dichiarazione avanzata per ciclo afferma: loop over intArray e memorizza il valore int di array corrente nella variabile currentValue.

Produzione:

1
3
5
7
9

Esempio: array di stringhe

Possiamo usare il ciclo for-each per scorrere su una matrice di stringhe. La dichiarazione del ciclo afferma: ciclo sull'array String myStrings e memorizzazione del valore String corrente nella variabile currentString.

String [] myStrings  = {
  "alpha",
  "beta",
  "gamma",
  "delta"
};

for(String currentString : myStrings) {
  System.out.println(currentString);
}

Produzione:

alpha
beta
gamma
delta

Esempio - Elenco

Il ciclo for avanzato può anche essere usato per iterare su java.util. Elenca come segue:

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);
}

La dichiarazione di loop indica: loop su myList List of Strings e memorizza il valore List corrente nella variabile currentItem.

Produzione:

alpha
beta
gamma
delta

Esempio: impostare

Il loop for avanzato può anche essere usato per iterare su un file java.util. Impostare come segue:

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);
}

Gli stati della dichiarazione loop: loop over mySet Set of Strings e memorizzano il valore Set corrente nella variabile currentItem. Si noti che poiché si tratta di un set, i valori di stringa duplicati non vengono memorizzati.

Produzione:

alpha
delta
beta
gamma

Fonte: loop in Java - Guida definitiva


4
public static Boolean Add_Tag(int totalsize)
{ List<String> fullst = new ArrayList<String>();
            for(int k=0;k<totalsize;k++)
            {
              fullst.addAll();
            }
}

3

Il linguaggio Java for-each può essere applicato solo ad array o oggetti di tipo * Iterable . Questo idioma è implicito in quanto veramente sostenuto da un Iteratore. L'iteratore è programmato dal programmatore e spesso utilizza un indice intero o un nodo (a seconda della struttura dei dati) per tenere traccia della sua posizione. Sulla carta è più lento di un normale ciclo continuo, almeno per strutture "lineari" come array e Liste ma fornisce una maggiore astrazione.


-1: questo è molto meno leggibile (in generale): anche il tuo esempio (il primo) è sbagliato, in quanto esclude il primo elemento dell'array.
Ondrej Skopek,

2

Sembra folle ma ehi funziona

List<String> someList = new ArrayList<>(); //has content
someList.forEach(System.out::println);

Questo funziona Magia


1
Ciò richiede Java 1.8 +
BARNI

2
non risponde nemmeno in remoto alla domanda
Tim

2

Come molte altre risposte affermano correttamente, for each loopè solo zucchero sintattico sullo stesso vecchio for loope il compilatore lo traduce nello stesso vecchio per loop.

javac (open jdk) ha un interruttore -XD-printflat, che genera un file java con tutto lo zucchero sintattico rimosso. il comando completo è simile al seguente

javac -XD-printflat -d src/ MyFile.java

//-d is used to specify the directory for output java file

Quindi consente di rimuovere lo zucchero sintattico

Per rispondere a questa domanda, ho creato un file e ho scritto due versioni di for each, una con arraye un'altra con una list. il mio javafile sembrava così.

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);
        }
    }
}

Quando ho compiledquesto file con l'interruttore sopra, ho ottenuto il seguente output.

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);
            }
        }
    }
}

Puoi vedere che insieme all'altro zucchero sintattico (Autoboxing) per ogni loop è stato cambiato in semplici loop.


-2
List<Item> Items = obj.getItems();
for(Item item:Items)
             {
                System.out.println(item); 
             }

Scorre tutti gli oggetti nella tabella Articoli.


1
L'utente non ha richiesto la sintassi
pradipgarala,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.