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>.


40 pensamientos en “Bucles for-each en Java”

  1. 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.

  2. 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);
        }
      }
    }
  3. 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 😉

  4. 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.

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

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

  7. @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};

  8. @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

  9. 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.

  10. 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.

  11. Pingback: Introducción a C# para programadores Java

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

  13. 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?

  14. 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

  15. 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

  16. En python seria mucho mas simple:

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

    y listo!!!!

  17. 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

  18. 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.

    1. 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

      1. 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.

      2. 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.

  19. Una linea. :p

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

  20. Y si quiero eliminar o mostrar una posición es posible? Según leo el eliminar no es posible pero como sería conocer una posición X sin manejo de indice? Apenas estoy aprendiendo y si me iluminan sería genial. Mil gracias.

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.