He decidido escribir de vez en cuando artículos mas básicos o esenciales del lenguaje Java para las personas que están empezando a manejar el lenguaje y este será el primero. Una de las situaciones mas habituales en la programación es recorrer una lista de elementos. En Java se puede realizar de varias maneras ,dos de las mas comunes son usando Java Iterator o usando un bucle forEach. Vamos a compararlas y ver algunas de las peculiaridades.
Definimos una lista de cadenas como la siguiente y la vamos a recorrer a través de un Iterador.
ArrayList < String > lista = new ArrayList <String> (); lista.add("Pedro"); lista.add("Olga"); lista.add("Miguel"); lista.add("Antonio"); lista.add("Pedro");
Un iterador es un objeto que nos permite recorrer una lista y presentar por pantalla todos sus elementos . Dispone de dos métodos clave para realizar esta operación hasNext() y next().
Iterator < String > it = lista.iterator(); while (it.hasNext()) { System.out.println(it.next()); }
Esto nos presentaría la lista de elementos por pantalla :
Pedro
Olga
Miguel
Antonio
Pedro
Java 5 y bucle foreach
A partir de Java 5 existe otra forma de recorrer una lista que es mucho mas cómoda y compacta , el uso de bucles foreach. Un bucle foreach se parece mucho a un bucle for con la diferencia de que no hace falta una variable i de inicialización :
for (String nombre: lista) { System.out.println(nombre); }
El resultado es claramente superior y mas legible para todo el mundo . ¿Es momento de dejar de usar iteradores para siempre? . La respuesta del público suele ser que sí . Sin embargo a veces los iteradores aportan cosas interesantes que los bucles foreach no pueden abordar.
Borrando elementos
Vamos a borrar todas las personas que se llaman “Pedro” de la lista . La operación parece tan sencilla como hacer lo siguiente:
for (String nombre: lista) { if (nombre.equals("Pedro")) { lista.remove("Pedro"); } }
Lamentablemente el código no funciona y lanza una excepción :
Tenemos un problema ya que la operación que queríamos realizar es sencilla ,pero falla escandalosamente ya que estamos recorriendo y modificando la lista a la vez. Es aquí donde los iteradores pueden venir a rescatarnos.
Java iterator y remove
El interface Iterator dispone de un método adicional que permite eliminar objetos de una lista mientras la recorremos (el método remove) :
Vamos a verlo en ejecución :
Iterator < String > it = lista.iterator(); while (it.hasNext()) { String nombre = it.next(); if (nombre.equals("Pedro")) { it.remove(); } }
El resultado será :
Olga
Miguel
Antonio
De esta forma podrémos eliminar elementos de una lista de forma segura:)
Hola, si por favor me pueden orientar. Cómo puedo aplicar el iterator en una collection ? Mi código antes era asi.. public void eliminarSimulacionAutomatica() { String ls_consecutivo; ls_consecutivo = FacesUtils.getStringFacesParameter(“consecutivo”); Collection clr_temp = new ArrayList(); clr_temp = getSimulacionLiquidacion(); if(StringUtils.isValidString(ls_consecutivo)) { for(Regfopep lr_temoral : getSimulacionLiquidacion()) { if(ls_consecutivo.trim().equalsIgnoreCase(StringUtils.getString(lr_temoral.getConsecutivo()))) { clr_temp.remove(lr_temoral); break; } } setSimulacionLiquidacion(clr_temp); } } // el uso del break es para evitar la exception java.util.ConcurrentModificationException –por el momento esta funcionando bien, me preocupa el uso del break, por eso mi interés en mejorarlo. He buscado como hacerlo y veo sobre la clase Iterator, lo implanté en mi código..ahora es asi… Read more »
Puede ser que la clase no te deje eliminar? . Es mejor solución tratarlo como una lista y acceder a remove
Ese error que comentas que sucede con el forEach al eliminar un elemento de la colección se puede solucionar con un simple break.
gracias por el aporte
No es una solución eficiente, ya que si en la lista tienes 3 elementos con el nombre de “Pedro”, al usar el break te sales del ciclo for y solo eliminaste un “Pedro” mientras los otros dos se quedaron en la lista, para estos casos de eliminar elementos repetidos en las listas (que es muy común) es mejor usar Iterator.
Muy bien explicado, lo pillé a la primera.
Muchas gracias,
Un saludo.
de nada 🙂
Hola podrian decirme como es para buscar un empleado por su nombre e indique si existe o no.
Iterator it= lista.iterator();
boolean encontro=false;
String buscarNombre=”Pedro”; // Empleado que se quiere buscar
while(it.hasNext() && !encontro) {
String nombre= it.next();
if (nombre.equals(buscarNombre)) {
encontro = true;
}
}
if (encontro)
System.out.println(“Se encontro el empleado :” +buscarNombre+ ” en la lista”);
Muy buena las indicaciones!
Podrías explicarme el siguiente código:
public float xxx(Curso c) {
float yyy=0;
for (Iterator iterator = cursos.iterator();iterator.hasNext();{
Curso curso = iterator.next();
if ((curso.getNombreCurso().equals(c.getNombre())){
List iterator = inscriptos.iterator();
for (Iterator iterator = inscriptos.ierator();
iterator.hastNext();)
{
Inscripcion inscripcion = iterator.next();
if (inscripcion.getNota() >= curso.getNotaAprobacion())
yyy++;
. }
}
}
if (c.getInscripciones().size() > 0)
return (yyy/c.getInscripciones().size())*100;
else return 0;
}
Busca en un curso determinado (pasado por parámetro) y cuenta la cantidad de inscriptos aprobados, y si hay al menos uno, devuelve el promedio (en porcentaje) de aprobados en ese curso. Está en el examen nro. 2 de 111mil programadores(en github), y si te fijas estan las resoluciones. No es un algoritmo muy complejo, pero tenes que familiarizarte mas con los bucles y practicar mucho y vas a ver que despues lo sacas enseguida. Un saludo y suerte!
creo que la gran diferencia entre iterator y forEach es que forEach recorre todo completo e iterator se puede detener en algún momento de la lista
gracias por el aporte 🙂
Muy buena las indicaciones!
Podrías explicarme el siguiente código: (creo que calcula el porcentaje de aprobados en cierto curso) Puede ser?
public float xxx(Curso c) {
float yyy=0;
for (Iterator iterator = cursos.iterator();iterator.hasNext();{
Curso curso = iterator.next();
if ((curso.getNombreCurso().equals(c.getNombre())){
List iterator = inscriptos.iterator();
for (Iterator iterator = inscriptos.ierator();
iterator.hastNext();)
{
Inscripcion inscripcion = iterator.next();
if (inscripcion.getNota() >= curso.getNotaAprobacion())
yyy++;
. }
}
}
if (c.getInscripciones().size() > 0)
return (yyy/c.getInscripciones().size())*100;
else return 0;
}
creo que recorre la lista de cursos y dentro de esa lista la lista de inscritos a cada uno , usando iteradores 🙂
Siempre puedes poner un break dentro del forEach y cancelar así la iteracción…
Hola Cecilio, me encantan tus artículos de Java. Siempre los leo y me ayudan muchísimo en mi trabajo.
Con respecto a tu planteo, propongo el siguiente código para una variante para continuar usando el foreach.
Es el siguiente:
// Código para usar el foreach pero iterando un array de los elementos de la lista.
List lista = new ArrayList();
lista.add(“Pedro”);
lista.add(“Olga”);
lista.add(“Miguel”);
lista.add(“Antonio”);
lista.add(“Pedro”);
for (Object nombre : lista.toArray()) {
if (nombre.equals(“Pedro”)) {
lista.remove(nombre);
}
}
System.out.println(lista);
———————————————————————
Un gran abrazo para vos.
Hola
Porqué es necesario pasar lista a Array() con lista.toArray en esta explicación?
Porque de esa manera se recorre el array y no la lista, de esa forma cuando se elimina el elemento la lista, esta se encuentra libre para poder hacer modificaciones.
Y asi evitas el error RUNTIME al eliminar un elemento en el recorrido de la lista.
eso 🙂
excelente… se entiende bien la explicacion
gracias 🙂
en el caso de que quiera eliminar un valor de tipo generico como podria hacerlo? lo entiendo cuando es de tip string, int, double, etc, pero cuando voy a pasar un parametro de tipo generico me da error.
Calculo que tendrás que hacer el iterador de tipo genérico también algo como Iterator
Muy bueno !! Gracias bien explicado me ayudo mucho !!
de nada 🙂
hola,me encantaria que me ayuden con un problema que tengo :/ : crear un programa con modulos para mostrar una lista de nombres por edades(categorias: niños, jovenes y adultos),tengo la idea, pero aun tengo dudas,gracias igual por la info.
[…] artículos relacionados: Iterator , […]
Exelente!!! A resuelto el problema que tenia! 🙂
me alegro 🙂
[…] Otros artículos relacionados: Java y Expresiones Lambda ,Java Iterator […]
import java.util.ArrayList;
import java.util.Iterator;
public class iterator_remove {
public static void main (String…vspec){
ArrayList lista = new ArrayList();
lista.add(“Nissan”);
lista.add(“Silvia”);
lista.add(“240sx”);
lista.add(“180sx”);
lista.add(“370z”);
lista.add(“Porsche”);
Iterator it= lista.iterator();
while(it.hasNext()) {
String nombre= it.next();
if (nombre.equals(“Porsche”)) {
it.remove();
System.out.println(“Este fume removido :”+nombre);
}
else{
System.out.println(“\t”+nombre);
}
}
}
}
hola, queria saber como recorrer una lista con un iterador mas de una vez
Puedes o volver a solicitar el iterador con iterator() o usar ListIterator como interface para ir hacia delante o hacia atrás 🙂
En tu ejemplo te funciona dado que termina cuando justo eliminas la entrada MARCOS, pero si intentas con otra entrada de MARCOS, te tira la excepción en cuestión.
Saludos!
Si te fijas bien eliminó como dijiste, pero no al correcto. Si bien encontró MARCOS, eliminó a su siguiente ‘RICARDO’.
Como se mencionó en este tutorial, la modificación y recorrido simultáneos, trae este conflicto, te altera la lista, como podes ver.
Saludos!
[…] artículos relacionados : forEach vs Iterator, Java Lambda Expressions ,Uso de […]
[…] artículos relacionados: ForEach vs Iterator , Expresiones […]
Acabo de probar la eliminación del contenido de la lista, ya que antes nunca me había salido el problema mencionado, pero no se replica y por el contrario se elimina bien. /** * @param argumentos */ public static void main( String[] argumentos ){ List listaNombres = new ArrayList(); listaNombres.add( “CESAR” ); listaNombres.add( “CARLOS” ); listaNombres.add( “MARCOS” ); listaNombres.add( “RICARDO” ); for( String vNombre : listaNombres) { System.out.println( vNombre ); if( vNombre.equals( “MARCOS” ) ){ listaNombres.remove( vNombre ); } } System.out.println( “” ); System.out.println( “listaNombres: [” + listaNombres + “]” ); } La impresión en consola es: CESAR CARLOS MARCOS listaNombres:… Read more »
pues suele ser habitual que jdk usas ? 🙂
Hola recien veo este sitio, y lo encuentro muy util como desarrollador java novato que quiere emprender hacia la cima hahaha , un saludo espero leer tu libro sobre arquitectura solida pronto. Por ahora seguire visitando el sitio para seguir aprendiendo. gracias por la info.
Lejos
me alegro te sea util el sitio
[…] Java Iterator vs ForEach […]
Estemmm…muy bueno. Sencillo, al grano y útil. Sigo esperando leer sobre inyecciones de dependencia. :p
Hombre mi libro trae bastante del tema 🙂
Que buen resumen, me la pase como a 1 hora intentando eliminar un objeto de una List que venia de una bd pero no podía y al final me encuentro con esto. Lo intentaré por hoy Saludos.
Me alegro te sea útil 🙂
Muy interesante tu aportación como siempre Cecilio. Ojalá también puedas hablarnos un poco mas sobre lo nuevo de java7 y lo que viene en Java8.
Me lo apunto 🙂
Buena idea la de esta serie. ¿Puedes escribir un día sobre genéricos? Para hacer buen uso de ellos y cómo/cuando aplicarlos, hacer las aplicaciones más seguras y escalables y al mismo tiempo entender mucho mejor tus ejemplos del 1° libro 😉
Me lo apunto para la próxima semana , porque si tenía intención de escribir sobre ellos 🙂