¿Cómo funciona el ciclo Java 'para cada'?

1499

Considerar:

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

¿Cómo sería el forbucle equivalente sin usar el para cada sintaxis?

Jay R.
fuente
Según JLS tiene dos formas: stackoverflow.com/a/33232565/1216775
akhil_mittal

Respuestas:

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

Tenga en cuenta que si necesita usarlo i.remove();en su bucle o acceder al iterador real de alguna manera, no puede usar el for ( : )idioma, ya que el iterador real simplemente se infiere.

Como señaló Denis Bueno, este código funciona para cualquier objeto que implemente la Iterableinterfaz .

Además, si el lado derecho de la for (:)expresión idiomática es un objeto en arraylugar de un Iterableobjeto, el código interno usa un contador de índice int y, en su array.lengthlugar, se compara. Consulte la Especificación del lenguaje Java .

nsayer
fuente
14
Acabo de llamar a un ciclo while como while (someList.hasMoreElements ()) {// do something}} : me acerca a la gracia de codificación que esperaba encontrar cuando busqué esta pregunta.
James T Snell el
66
Consulte también docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html que explican el bucle foreach (cuando se introdujo)
PhoneixS
1
para desarrolladores de Android Studio: import java.util.Iterator;yimport java.lang.Iterable;
dsdsdsdsd
Frustrantemente, java.util.Iteratorno se implementa, Iterablepor lo que no puede for(String s : (Iterator<String>)foo). Entiendo por qué es esto, pero es irritante.
Christopher Schultz
499

La construcción para cada uno también es válida para matrices. p.ej

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

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

que es esencialmente equivalente a

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

Entonces, resumen general:
[nsayer] La siguiente es la forma más larga de lo que está sucediendo:

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

Tenga en cuenta que si necesita usar i.remove (); en su bucle, o acceder al iterador real de alguna manera, no puede usar el idioma for (:), ya que el iterador real simplemente se infiere.

[Denis Bueno]

Está implícito en la respuesta de nsayer, pero vale la pena señalar que los OP para la sintaxis (..) funcionarán cuando "someList" sea algo que implemente java.lang.Iterable: no tiene que ser una lista o una colección de java.util. Incluso sus propios tipos, por lo tanto, se pueden usar con esta sintaxis.

Mikezx6r
fuente
161

El foreachbucle , agregado en Java 5 (también llamado "bucle mejorado para"), es equivalente a usar un java.util.Iteratorazúcar sintáctico --it para la misma cosa. Por lo tanto, al leer cada elemento, uno por uno y en orden, foreachsiempre se debe elegir un en lugar de un iterador, ya que es más conveniente y conciso.

para cada

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

Iterador

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

Hay situaciones en las que debe usar un Iteratordirectamente. Por ejemplo, intentar eliminar un elemento mientras se usa una foreachlata (¿será?) Resultará en a ConcurrentModificationException.

foreachvs for.: diferencias básicas

La única diferencia práctica entre fory foreaches que, en el caso de los objetos indexables, no tiene acceso al índice. Un ejemplo cuando forse requiere el bucle básico :

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

Aunque podría crear manualmente una variable int de índice separada con foreach,

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

no se recomienda, ya que el alcance variable no es ideal, y el forbucle básico es simplemente el formato estándar y esperado para este caso de uso.

foreachvs for.: rendimiento

Al acceder a colecciones, a foreaches significativamente más rápido que el foracceso a la matriz del bucle básico . Sin embargo, al acceder a matrices, al menos con matrices primitivas y envolventes, el acceso a través de índices es dramáticamente más rápido.

Momento de la diferencia entre el iterador y el acceso al índice para matrices int primitivas

Los índices son 23- 40 por ciento más rápido que cuando se accede a los iteradores into Integermatrices. Aquí está el resultado de la clase de prueba en la parte inferior de esta publicación, que suma los números en una matriz primitiva-int de 100 elementos (A es iterador, B es índice):

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

También ejecuté esto para una Integermatriz, y los índices siguen siendo el claro ganador, pero solo entre un 18 y un 25 por ciento más rápido.

Para las colecciones, los iteradores son más rápidos que los índices.

Para algunos Listde Integers, sin embargo, los iteradores son el claro ganador. Simplemente cambie la matriz int en la clase de prueba a:

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

Y realice los cambios necesarios en la función de prueba ( int[]to List<Integer>, lengthto 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)

En una prueba son casi equivalentes, pero con las colecciones, el iterador gana.

* Esta publicación se basa en dos respuestas que escribí en Stack Overflow:

Más información: ¿Cuál es más eficiente, un ciclo para cada uno o un iterador?

La clase de prueba completa

Creé esta clase de comparar el tiempo que se tarda en hacer dos cosas después de leer esta pregunta en Stack Overflow:

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

}
mente mental
fuente
44
Esta respuesta ahora es una publicación de blog y se creó a partir de dos respuestas relacionadas que he escrito: aquí y aquí . También incluye una clase genéricamente útil para comparar la velocidad de dos funciones (en la parte inferior).
aliteralmind
1
Solo un comentario menor aquí, no debe indicar categóricamente que la sintaxis de (:) siempre es mejor para acceder a las colecciones; Si está utilizando una lista de matriz, el bucle for (:) será aproximadamente 2 veces más lento que el uso de for (int i = 0, len = arrayList.size (); i <len; i ++). Creo que mencionaste eso en el enlace [link] ( stackoverflow.com/questions/2113216/… ) de todos modos, pero es importante destacar que ...
Leo
@Leo Es un buen punto. Una ArrayList es Collection, pero está respaldada por una matriz, por lo que lo normal es mejor para ella.
aliteralmind
Me imagino que for(int value : int_array) {/* loop content */}es el más lento en su prueba porque es sintácticamente equivalente a for(int i = 0; i < int_array.length; i++) {int value = int_array[i]; /* loop content */}, que no es lo que compara su prueba.
daiscog
(por cierto, no digo que su prueba no sea válida, pero podría valer la pena señalar las razones detrás de la diferencia para que las personas puedan elegir lo que es correcto para su escenario particular. Si están haciendo una prueba int value = int_array[i];al comienzo de su prueba) bucle, entonces también podrían usar foreach. A menos que también necesiten acceso al índice, por alguna razón. En resumen, todo depende del contexto.)
daiscog
129

Aquí hay una respuesta que no asume el conocimiento de los iteradores de Java. Es menos preciso, pero es útil para la educación.

Mientras programamos, a menudo escribimos código similar al siguiente:

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 sintaxis foreach permite que este patrón común se escriba de una manera más natural y menos sintácticamente ruidosa.

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

Además, esta sintaxis es válida para objetos como Listas o Conjuntos que no admiten la indexación de matrices, pero que implementan la interfaz Iterable de Java.

MRocklin
fuente
40

El ciclo for-each en Java usa el mecanismo de iterador subyacente. Entonces es idéntico a lo siguiente:

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

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

En las características de Java 8 puede usar esto:

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

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

Salida

First
Second
Third
Jrovalle
fuente
77
esta información aleatoria ni siquiera responde remotamente la pregunta
Tim
25

Está implícito en la respuesta de nsayer, pero vale la pena señalar que los OP para la sintaxis (..) funcionarán cuando "someList" sea algo que implemente java.lang.Iterable: no tiene que ser una lista o una colección de java.util. Incluso sus propios tipos, por lo tanto, se pueden usar con esta sintaxis.

EfForEffort
fuente
1
fd es correcto: el código interno cuando el lado derecho del idioma for (:) usa un int y array.length en lugar de buscar un iterador. forums.sun.com/thread.jspa?messageID=2743233
nsayer
24

Como se define en JLS , cada ciclo puede tener dos formas:

  1. Si el tipo de expresión es un subtipo de, Iterableentonces la traducción es como:

    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. Si la expresión necesariamente tiene un tipo de matriz, T[]entonces:

    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 introducido transmisiones que generalmente funcionan mejor. Podemos usarlos como:

someList.stream().forEach(System.out::println);
Arrays.stream(someArray).forEach(System.out::println);
akhil_mittal
fuente
2
La respuesta más relevante y precisa. Encantado por tiene dos traducciones de hecho.
Zarial
23

Una sintaxis de bucle foreach es:

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

Ejemplo:

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

Salida:

Java
Coffe
Is
Cool

ADVERTENCIA: puede acceder a los elementos de la matriz con el bucle foreach, pero NO puede inicializarlos. Use el forbucle original para eso.

ADVERTENCIA: debe hacer coincidir el tipo de matriz con el otro objeto.

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

Si desea editar elementos, use el forbucle original de esta manera:

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

Ahora si volcamos s a la consola, obtenemos:

hello
2 is cool
hello
hello
PrivateName
fuente
21

La construcción de bucle "para cada" de Java permitirá la iteración sobre dos tipos de objetos:

  • T[] (matrices de cualquier tipo)
  • java.lang.Iterable<T>

La Iterable<T>interfaz tiene un solo método: Iterator<T> iterator(). Esto funciona en objetos de tipo Collection<T>porque la Collection<T>interfaz se extiende Iterable<T>.

Ryan Delucchi
fuente
16

El concepto de un bucle foreach como se menciona en Wikipedia se destaca a continuación:

Sin embargo, a diferencia de otras construcciones de bucle for, los bucles foreach generalmente no mantienen un contador explícito : esencialmente dicen "hacer esto a todo en este conjunto", en lugar de "hacer esto x veces". Esto evita posibles errores fuera de uno y hace que el código sea más fácil de leer.

Entonces, el concepto de un bucle foreach describe que el bucle no usa ningún contador explícito, lo que significa que no hay necesidad de usar índices para recorrer la lista, por lo que salva al usuario del error de uno por uno. Para describir el concepto general de este error off-by-one, tomemos un ejemplo de un ciclo para recorrer en una lista usando índices.

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

}

Pero suponga que si la lista comienza con el índice 1, este bucle generará una excepción, ya que no encontrará ningún elemento en el índice 0 y este error se llama error de uno por uno. Entonces, para evitar este error off-by-one, se utiliza el concepto de un bucle foreach. También puede haber otras ventajas, pero creo que este es el concepto principal y la ventaja de usar un bucle foreach.

oneConsciousness
fuente
13

En Java 8, presentaron para cada uno. Usando la lista, los mapas se pueden enlazar.

Repetir una lista usando para cada

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

Recorrer un mapa usando para cada

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);
});
vivekkurien
fuente
12
for (Iterator<String> itr = someList.iterator(); itr.hasNext(); ) {
   String item = itr.next();
   System.out.println(item);
}
Roger Lindsjö
fuente
11

El uso de versiones anteriores de Java, incluido el Java 7uso de foreachbucle, de la siguiente manera.

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

La siguiente es la última forma de usar el foreachbucle enJava 8

(repita una lista con la forEachexpresión + lambda o referencia de método)

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

Para más información consulte este enlace.

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

Dulith De Costa
fuente
10

Aquí hay una expresión equivalente.

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

También tenga en cuenta que el uso del método "foreach" en la pregunta original tiene algunas limitaciones, como no poder eliminar elementos de la lista durante la iteración.

El nuevo bucle for es más fácil de leer y elimina la necesidad de un iterador separado, pero solo es realmente utilizable en pases de iteración de solo lectura.

billjamesdev
fuente
1
En esos casos, el uso de removeIfpodría ser la herramienta adecuada
ncmathsadist
9

Una alternativa a forEach para evitar su "para cada uno":

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

Variante 1 (simple):

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

Variante 2 (ejecución paralela (más rápida)):

someList.parallelStream().forEach(listItem -> {
    System.out.println(listItem);
});
Alexander Drobyshevsky
fuente
2
Debería haber mencionado que se agregó en Java 1.8
TheLibrarian
No podemos estar 100% seguros de que se use el mismo hilo. Me gusta usar el for(formulario si me gusta asegurarme de que se usa el mismo hilo. Me gusta usar la forma de flujo si me gusta permitir la ejecución multiproceso.
Grim
8

Agrega belleza a su código al eliminar todo el desorden de bucle básico. Le da un aspecto limpio a su código, justificado a continuación.

forBucle normal :

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

Usando para cada uno:

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

for-each es una construcción sobre una colección que implementa Iterator . Recuerde que su colección debe implementar Iterator ; de lo contrario no puede usarlo para cada uno.

La siguiente línea se lee como " para cada TimerTask t en la lista " .

for (TimerTask t : list)

Hay menos posibilidades de errores en el caso de for-each. No tiene que preocuparse por inicializar el iterador o inicializar el contador de bucle y terminarlo (donde hay margen para errores).

Manohar
fuente
8

Antes de Java 8, debe usar lo siguiente:

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

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

Sin embargo, con la introducción de Streams en Java 8 puede hacer lo mismo con mucha menos sintaxis. Por ejemplo, para tu someListpuedes hacer:

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

Puede encontrar más información sobre las transmisiones aquí .

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

Se vería algo así. Muy asqueroso.

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

Hay una buena valoración crítica en cada en la documentación de Sun .

Pete
fuente
6

Como tantas buenas respuestas dicen, un objeto debe implementar el Iterable interfacesi quiere usar unfor-each bucle.

Publicaré un ejemplo simple e intentaré explicar de una manera diferente cómo un for-each bucle.

El for-eachejemplo del bucle:

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

Luego, si usamos javappara descompilar esta clase, obtendremos esta muestra de código de bytes:

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;

Como podemos ver en la última línea de la muestra, el compilador convertirá automáticamente el uso de la for-eachpalabra clave al uso de un Iteratoren tiempo de compilación. Eso puede explicar por qué el objeto, que no implementa el Iterable interface, arrojará un Exceptioncuando intente usar el for-eachbucle.

L Joey
fuente
6

El Java para cada bucle (también conocido como bucle mejorado) es una versión simplificada de un bucle for. La ventaja es que hay menos código para escribir y menos variables para administrar. La desventaja es que no tiene control sobre el valor del paso y no tiene acceso al índice del bucle dentro del cuerpo del bucle.

Se utilizan mejor cuando el valor del paso es un simple incremento de 1 y cuando solo necesita acceso al elemento de bucle actual. Por ejemplo, si necesita recorrer todos los elementos de una matriz o colección sin mirar por delante o por detrás del elemento actual.

No hay inicialización de bucle, no hay condición booleana y el valor del paso es implícito y es un incremento simple. Es por eso que se consideran mucho más simples que los regulares para los bucles.

Los bucles mejorados siguen este orden de ejecución:

1) cuerpo de bucle

2) repita desde el paso 1 hasta que se haya recorrido toda la matriz o colección

Ejemplo: matriz de enteros

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

La variable currentValue contiene el valor actual que se está repitiendo en la matriz intArray. Observe que no hay un valor de paso explícito: siempre es un incremento de 1.

Se puede pensar que el colon significa "en". Por lo tanto, los estados de declaración de bucle for mejorados: repiten sobre intArray y almacenen el valor int de la matriz actual en la variable currentValue.

Salida:

1
3
5
7
9

Ejemplo: matriz de cadenas

Podemos usar el ciclo for-each para iterar sobre una matriz de cadenas. La declaración de bucle indica: repita sobre la matriz de cadenas myStrings y almacene el valor de cadena actual en la variable currentString.

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

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

Salida:

alpha
beta
gamma
delta

Ejemplo: lista

El bucle for mejorado también se puede usar para iterar sobre java.util.List de la siguiente manera:

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 declaración de bucle dice: repita sobre myList List of Strings y almacene el valor de List actual en la variable currentItem.

Salida:

alpha
beta
gamma
delta

Ejemplo: conjunto

El bucle for mejorado también se puede usar para iterar sobre un java.util.Set de la siguiente manera:

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

La declaración de bucle dice: bucle sobre mySet Set of Strings y almacene el valor Set actual en la variable currentItem. Tenga en cuenta que como se trata de un conjunto, los valores de cadena duplicados no se almacenan.

Salida:

alpha
delta
beta
gamma

Fuente: Loops en Java - Guía definitiva

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

El lenguaje para cada Java solo se puede aplicar a matrices u objetos de tipo * Iterable . Este modismo está implícito, ya que realmente está respaldado por un iterador. El programador programa el iterador y, a menudo, utiliza un índice entero o un nodo (según la estructura de datos) para realizar un seguimiento de su posición. En el papel, es más lento que un ciclo for regular, al menos para estructuras "lineales" como matrices y listas, pero proporciona una mayor abstracción.

TheArchon
fuente
-1: esto es mucho menos legible (generalmente): incluso su propio ejemplo (el primero) es incorrecto, ya que omite el primer elemento de la matriz.
Ondrej Skopek
2

Esto se ve loco pero bueno, funciona

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

Esto funciona. magia

Rei Brown
fuente
1
Esto requiere Java 1.8 +
BARNI
2
ni siquiera responde remotamente la pregunta
Tim
2

Como muchas de las otras respuestas dicen correctamente, el for each loopazúcar sintáctico es solo sobre el mismo viejo for loopy el compilador lo traduce al mismo bucle for antiguo.

javac (open jdk) tiene un interruptor -XD-printflat, que genera un archivo java con todo el azúcar sintáctico eliminado. el comando completo se ve así

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

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

Entonces, eliminemos el azúcar sintáctico

Para responder a esta pregunta, creé un archivo y escribí dos versiones de for each, una con arrayy otra con un list. mi javaarchivo se veía así.

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

Cuando compiledeste archivo con el interruptor anterior, obtuve el siguiente resultado.

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

Puede ver que junto con el otro azúcar sintáctico (Autoboxing) para cada bucle se cambió a bucles simples.

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

Itera sobre todos los objetos en la tabla Artículos.

shubhranshu
fuente
1
El usuario no ha solicitado la sintaxis
pradipgarala