Bucles for-each en Java

Por poca experiencia que tengas con Java seguramente conozcas el uso de los típicos bucles for. Lo que puede que no conozcas si aprendiste Java hace tiempo o si solo lo tocaste muy por encima es el nuevo for mejorado que se introdujo en Java 5 (Tiger) que facilita recorrer las colecciones y que funciona de forma similar a los bucles for in de Python o los foreach de PHP.

Para recorrer una colección antes de Java 1.5 podíamos usar, por ejemplo, algo como lo siguiente (de hecho no algo exactamente igual, porque tampoco existían los generics, pero este no es el objeto del artículo):

import java.util.Arrays;
import java.util.List;

public class Ejemplo {
  public static void main(String args[]) {
    List<String> lenguajes = Arrays.asList("Java", "Python", "Ruby", "C#");

    for (int i = 0; i < lenguajes.size(); i++) {
      String lenguaje = lenguajes.get(i);
      System.out.println("Me gusta " + lenguaje);
    }
  }
}

También podríamos utilizar iteradores:

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class Ejemplo {
  public static void main(String args[]) {
    List<String> lenguajes = Arrays.asList("Java", "Python", "Ruby", "C#");
    Iterator <String> iterador = lenguajes.iterator();

    while (iterador.hasNext()) {
      String lenguaje = iterador.next();
      System.out.println("Me gusta " + lenguaje);
    }
  }
}

Usando la nueva construcción para el bucle for el código sería tan sencillo y elegante como esto:

import java.util.Arrays;
import java.util.List;

public class Ejemplo {
  public static void main(String args[]) {
    List<String> lenguajes = Arrays.asList("Java", "Python", "Ruby", "C#");

    for (String lenguaje : lenguajes)
      System.out.println("Me gusta " + lenguaje);
  }
}

Es decir, para cada elemento en la colección lenguajes, asignamos el valor a una nueva variable de tipo String lenguaje, y ejecutamos el cuerpo del bucle.

Este tipo de bucle puede recorrer cualquier clase que implemente la interfaz Iterable<E>.


Comentarios
  1. Interesante cuanto menos… yo me seguiré quedando con la primera forma… uno aprendió así…

    Responder

  2. Lo siento, no me he podido resistir a comentar la jugada del foreach en C#:

    foreach (string lenguaje in lenguajes)
    Console.WriteLine(“Me gusta ” + lenguaje);

    SaludoX.

    Responder

  3. Ya era hora de que pusieran el foreach ya que los Iterators eran la solución “mediocre” a esta construcción del lenguaje.

    Y digo mediocre porque usar un Iterator implica tener dos clases (la lista y el iterador) y que cada una tenga acceso a la otra (probablemente a las propiedades privadas de la otra; en C++ se hace con la palabra reservada ‘friend’ y en Java si están dentro del mismo paquete, cosa que me parece otra chapuza).

    De hecho, a cualquier elemento que se le pueda aplicar el operador [] se puede meter en un foreach y creo que es bastante más fácil (y tiene mejor rendimiento) que usar el iterador.

    Responder

  4. Hay otra forma de usar el Iterator que es bastante más elegante y cómoda, con bucles for también. Sería algo así:

    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.List;
    
    public class Ejemplo {
      public static void main(String args[]) {
        List lenguajes = Arrays.asList("Java", "Python", "Ruby", "C#");
    
        for (Iterator iterador = lenguajes.iterator(); iterador.hasNext(); ) {
          String lenguaje = iterador.next();
          System.out.println("Me gusta " + lenguaje);
        }
      }
    }

    Responder

  5. A mí me gusta más con un while, aunque la verdad es que es por una tontería, una cuestión de estética más que nada. Simplemente me parece feo tener un for que no tenga los 3 componentes.

    Te lo pongo dentro de un pre para que se entienda mejor 😉

    Responder

  6. saasd

    la gracia del foreach en php, al recorrer un array por ejemplo, es poder kedarte con el valor de acceso.

    Asi pues, si tienes un $a = array(“numero” => 2, “color” => “amarillo”) y haces un foreach($a as $key=>$value) tienes por un lado la clave, y por el otro, el valor.

    Responder

  7. No sabia que en java, se podian manejar los for tipo python, pero como dicen por ahi, yo tambien me crie con los for con 3 parametros. XD

    Responder

  8. Ig

    Si combinamos la eficiencia japonesa y su natural elegancia obtenemos una única línea de código que hace lo mismo que 7 de java.

    ([‘Ruby’, ‘Python’]).each { |lenguaje| puts ‘%s mola’ % [lenguaje] }

    Responder

  9. Linkamp

    Otra de las mejores en Java 5 es el paso de argumentos variables a un metodo, por ejemplo

    public void habla(String … palabras){
    for(String palabra : palabras){
    System.out.println(palabra);
    }
    }

    Responder

  10. @Linkamp Ya que lo comentas, también se añadió el autoboxing/unboxing, para convertir los tipos primitivos en los wrappers asociados y viceversa automáticamente (por ejemplo un int en Integer e Integer en int).

    List<Integer> numeros = new ArrayList<Integer>();
    int numero = 0;
    numeros.add(numero);

    Y también el tipo enum:
    enum Dia {LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO};

    Responder

  11. Linkamp

    @Zootropo No sabía que en el 1.4 no estava, lo he utilizado algunas veces sin prestarles mucha atención, aunque es de ayuda. hasta donde yo se creo que el salto fue bastante más grande de la 1.4 a la 1.5, que de la 1.5 a la 1.6.

    Saludos y felicidades por la página

    Responder

  12. Desde que conozco el foreach de java me cuesta tener que volver a los iteradores. Gran apunte que me costa mucha gente no conoce.

    Un saludo

    Responder

  13. Es interesante apuntar que, al final, el código generado es el mismo para el for-each y la versión con iteradores. Es decir, no es nada más que ‘syntactic sugar’ como casi todas las ventajas que habeis comentado de Java 1.5 (incluyendo los genéricos, por desgracia). Una pena….

    Saludos.

    Responder

  14. Interesante Fernando, mas tela para los detractores de java

    Responder

  15. metaphorax

    Que sorpresa ver que esta implementado en Java. En c# el foreach saca de muchos aprietos al obtener los valores de los controles agrupados en un “form”. Ahora a experimentar si tiene el mismo poder en Java. Esperemos que sí, aunque no me gusta mucho Java.. pero es casi forzoso aprenderlo ó t quedas rezagado.

    Responder

  16. juan

    ps yo me quedo con el while es simplemente mejor que un for sin los 3 componentes

    Responder

  17. […] bucle foreach tiene una palabra clave propia, a diferencia de Java, que utiliza for. La sintaxis es parecida, sustituyendo los dos puntos (:) de Java por la palabra […]

    Responder

  18. lol

    quiero saber sobre la herencia en java

    Responder

  19. matias

    deckerix no quiere avanzar que pena si hay algo mejor porque no usarlo, que rara actitud…

    Responder

  20. Santiago

    muy educativo, gracias me ayudo mucho. y bueno que hayas tomado en cuenta los genericos no existen muchas paginas con esta informacion.

    Responder

  21. Walter

    En C# cuando se usa el foreach, no se puede modificar el valor de cada elemento miembro. Me pueden confirmar si lo mismo aplica a esta estructura for de Java?

    Responder

  22. fernando

    Y qué pasa con el rendimiento? cual es mejor de cara al rendimiento? me lo podeis indicar? me seria de gran ayuda. Gracias

    Responder

  23. Amigo realmente te doy las gracias precisamente estoy siguiendo los cursos de Jesus del conde lo recomiendo http://www.mefeedia.com/watch/28388902
    y busque y busque al final aprendi en tu web 😀 saludos desde el DF

    Responder

  24. janier

    ps yo tambien me acostumbre al for con 3 parametros pero el for each esta mas simple me gusta el nuevo buqle

    Responder

  25. mauricio

    el este bucle salio desde la “5” es muy bueno cuando recorres un vector que es lo que manejo bastante
    eso de quedarse con las 3 partes del for la verdad es porque no has entendido este bucle de 2 partes
    pues lo explico un poco
    for( : ){
    system.out.println(.);
    }
    es muy facil me costo un poco entenderlo pero eso no quiso decir que me quedara con la forma que solo yo entiendo, hay que ser recursivo

    Responder

  26. bryan

    jaja al parecer escribite sin contar que lo hiciste en html por eso no te salio.
    te apoyo es muy facil el bucle
    hay que practicarlo para aprenderlo bien

    Responder

  27. jcswach

    lo interesante sería manejar un array bidimensional con for each.

    Responder

  28. Kevin Arnold

    Chévere ha…

    aquí les dejo una web donde se postea temas en java desde lo básico hasta lo avanzado…
    http://www.todoenjava.blogspot.com

    Responder

  29. Sergio

    Hola, quisiera saber como recorrer al revez, del fianl al inicio utilizando el for each? gracias.

    Responder

  30. Patas verdes

    En python seria mucho mas simple:

    lenguajes = [‘Python’,’C#’,’Java’,’Perl’]
    for i in lenguajes:
    print “Me gusta”+ str(i)

    y listo!!!!

    Responder

  31. os

    Hola alguien sabe porque me da fallo al ejecutar estos códigos en eclipse? el fallo está en la siguiente línea:
    List lenguajes = Arrays.asList(“Java”, “Python”, “Ruby”, “C#”);

    El error que me da es el siguiente:
    Exception in thread “main” java.lang.Error: Unresolved compilation problem:
    The type List is not generic; it cannot be parameterized with arguments

    at aRRAY.ForEach.varios.Array1.main(Array1.java:8)

    Sólo pasa en eclipse, ya que en la consola el programa ejecuta sin problemas.
    alguna idea?? Gracias

    Responder

    • Tony

      @os
      List lenguajes = Arrays.asList(“Java”, “Python”, “Ruby”, “C#”);

      Así te resolvería el problema.

      Responder

  32. Manuel

    Me quedo con el de php, por simplicidad y potencia.

    Responder

  33. LuisT

    Para mejorar un poco la primera forma, podrías sacar la función size del for para que no se ejecutara la función en cada iteración, simplemente poniendo el valor de size en una variable tamaño por ejemplo.

    Responder

    • miquel

      LuisT, como sabes que la funcion se repite en cada iteracion.
      si haces un for que elimine alguno de los objetos de un ArrayList, te darás cuenta que si por ejemplo hay 10 elementos y eliminas el 4, cuando el for llega a la posicion 10, intenta leerla, si fuera como tu dices, despues de eliminar el elemento 4, se volveria a leer el size y el for se daria cuenta que hay 9 elementos y no 10.
      yo diria que el size lo ejecuta al iniciar el for y ya no lo vuelve a ejecutar.
      se tiene que vigilar con lo que se dice, si no lo sabes con seguridad no lo afirmas, por el contrario no está de mas decir que solo es una opinion

      Responder

      • Lothar

        LuisT tiene razón, por mucho que te pese. En tu caso en el que habría una modificación del tamaño del array, por supuesto que no tendría sentido, pero este no es el caso.

        Por otra parte, no rellamar al método size tiene sus ventajas en cuanto a procesamiento. Por otro lado, declarar una variable para algo tan pequeño es una desventaja e cuanto a memoria.

        Tanto las ventajas como desventajas son ínfimias y no serían notables con equipos de hoy en día. Pero si hay que recorrer un array que no modifica su tamaño y tiene 150000 elementos o más, la desventaja de memoria se convierte en una gran ventaja frente a la cantidad de llamadas al método nombrado.

        Hay que tener algo en mente, y es que en lo que se refiere a ARRAYS exclusivamente, tenemos .length, que almacena el valor del tamaño del array y tiene comportamiento de variable (de solo lectura, me parece).

        Un saludo.

        Responder

      • Lothar

        Ah, y no sé qué versión de Java usarías tú en esa época, pero ahora mismo yo me he fijado que mis fors leen la condición con cada lectura, llamando a las funciones/métodos o como quieras llamarlas y que estén en ella.

        Responder

  34. bueno en java representar un foreach! es de la siguiente manera:

    for(String algo: ListaString){

    //Código aquí
    }
    Si tienen dudas estamos dispuestos a ayudar 😀

    Saludos

    Responder

  35. David

    Una linea. :p

    for (String lenguaje : Arrays.asList(“Java”,”Python”, “Ruby”, “C#”)) System.out.println(“Me gusta ” + lenguaje); }

    Responder

Deja un comentario