Autor Tema: java.util.ConcurrentModificationException al eliminar item de colección  (Leído 28009 veces)

Susana83

  • Sin experiencia
  • *
  • Mensajes: 49
    • Ver Perfil
El ejercicio dice

a partir de este código corregirlo para que se realice la eliminacion de un elemento de la lista en tiempo dinámico.

Código: [Seleccionar]
import java.util.ArrayList;

public class Ejecutar{
  public static void main(String args[]) {
    ArrayList<String> list = new ArrayList<String>();

    list.add("Bart");
    list.add("Lisa");
    list.add("Marge");
    list.add("Barney");
    list.add("Homer");
    list.add("Maggie");

    for(String s: list)
    {
      if (s.equals("Barney")) {
        list.remove("Barney");
      }
      System.out.println(s);
    }
  }
}

Pero obtengo un error java.util.ConcurrentModificationException ¿qué puede estar pasando?

Gracias por adelantado
« Última modificación: 01 de Octubre 2014, 10:46 por Alex Rodríguez »

Jorge lopez

  • Sniper
  • Intermedio
  • ***
  • APR2.COM
  • Mensajes: 248
  • @SniperOfElite
    • Ver Perfil
Re:ejercicio java
« Respuesta #1 en: 28 de Septiembre 2014, 22:29 »
 Hola Susana83!

Sobre el error java.util.ConcurrentModificationException te cito lo siguiente:
Citar
El uso del bucle for-each tiene algunos inconvenientes. Uno de ellos, que para recorrer la colección nos
basamos en la propia colección y por tanto no podemos (o al menos no debemos) manipularla durante
su recorrido. Supongamos que vamos recorriendo una lista de 20 objetos y que durante el recorrido
borramos 5 de ellos. Probablemente nos saltará un error porque Java no sabrá qué hacer ante esta
modificación concurrente.

Sería como seguir un camino marcado sobre unas baldosas y que durante el camino nos movieran las
baldosas de sitio: no podríamos seguir el camino previsto. Este tipo de problemas se suelen presentar
con un mensaje de error del tipo java.util.ConcurrentModificationException.

Lo que se explica en esta cita, es que si tratas de recorrer una colección (lista, ArrayList, ect..) y al mismo tiempo intentar realizar cambios sobre esta, lo mas probable es que obtengas un error de tipo java.util.ConcurrentModificationException

La solución a esto es hacer uso de la clase Iterator de la librería de java. Te recomiendo que estudies la entrega CU00667B del curso, aprender programación java desde cero : https://www.aprenderaprogramar.com/index.php?option=com_content&view=article&id=633:tipo-iterator-api-java-ejemplo-error-javautilconcurrent-modificationexception-resumen-bucles-cu00667b&catid=68:curso-aprender-programacion-java-desde-cero&Itemid=188 Aquí encontraras mas detalles sobre la clase Iterator y como usarla para sacar adelante tu ejercicio. Luego que estudies e implementes lo aprendido en tu ejercicio, pues nos comentas a ver como te ha ido.

Si en cualquier momento necesitas ayuda, o consultar algo no dudes en preguntar.

Saludos!

« Última modificación: 29 de Septiembre 2014, 01:07 por Sniper »
while(estesVivo)
{
  aprende();
  ayuda();
  enseña();
}
if(mueres){teRecordaran();}

Susana83

  • Sin experiencia
  • *
  • Mensajes: 49
    • Ver Perfil
Re:ejercicio java
« Respuesta #2 en: 29 de Septiembre 2014, 11:32 »
Sniper gracias por orientarme he modificado el código con Iterator pero sigo teniendo un error

Código: [Seleccionar]
import java.util.ArrayList;
import java.util.Iterator;

public class Ejecutar{
  public static void main(String args[]) {
    ArrayList<String> list = new ArrayList<String>();

    list.add("Bart");
    list.add("Lisa");
    list.add("Marge");
    list.add("Barney");
    list.add("Homer");
    list.add("Maggie");

    Iterator<String> recorrer = list.iterator();
   
    while (recorrer.hasNext()) {
   
        String nombre = recorrer.next();
      if (nombre.equals("Barney")) {
        list.remove("Barney");
      }
      System.out.println(nombre);
    }
  }
}

Jorge lopez

  • Sniper
  • Intermedio
  • ***
  • APR2.COM
  • Mensajes: 248
  • @SniperOfElite
    • Ver Perfil
Re:ejercicio java
« Respuesta #3 en: 29 de Septiembre 2014, 20:16 »
 Hola Susana83!

Mirando tu codigo se nota que has estudiado sobre la clase Iterator, también puedo ver que has sustituido el bucle for each por un bucle while en conjunto con Iterator y algunos de sus métodos.

Aunque hasta este punto aun el código no funciona como se espera, por el hecho de a ver sustituido el bucle for-each por un bucle while, y haciendo uso de algunos métodos de la clase Iterator en este bucle, se puede decir que tu código a evolucionado en la dirección correcta.

Ahora te are algunas aclaraciones para que seas capas de comprender el porque del error (java.util.ConcurrentModificationException) en tiempo de ejecución que nos continua saltando al ejecutar el programa, y para que una vez lo asimiles puedas corregirlo.

Cuando recorremos una coleccion digamos que con un bucle for-each y mientras la recoremos intentamos manipular la lista nos salta el error java.util.ConcurrentModificationException, para corregir esto usamos el método iterator de la clase Iterator sobre la coleccion que queramos recorrer y manipular al mismo tiempo, pero los métodos de manipulación los provee la clase Iterator y se invocan desde el Iterator creado, en este caso "recorrer". Por tanto una sintaxis como:
Código: [Seleccionar]
if (nombre.equals("Barney")) {
        list.remove("Barney");
      }
dara lugar a que salte el error java.util.ConcurrentModificationException, la sintaxis correcta seria:
Código: [Seleccionar]
if (nombre.equals("Barney")) {
        recorrer.remove();
      }

Donde lo que se indica es, que si el ultimo objeto analizado en el Iterator "recorrer" es igual (igualdad, parentesco) al objeto "Barney" pues que se ejecute el metodo.remove(); y elimine este objeto, dicha eliminación se refleja en el ArrayList "list".

Si ahora utilizas un bucle for-each para recorrer y mostrar por pantalla los elementos (objetos) que contiene la colección "list" comprobaras que ahora "Barney" ha sido expulsado (removido, eliminado  ;D) de la familia Simpson, y que ahora esta lista contiene solo 5 objetos.

A continuación te dejo una forma que podría ser una solución a este ejercicio:

Código: [Seleccionar]
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

public class Ejecutar{
  public static void main(String args[]) {
    List<String> list = new ArrayList<String>();

    list.add("Bart");
    list.add("Lisa");
    list.add("Marge");
    list.add("Barney");
    list.add("Homer");
    list.add("Maggie");

    Iterator<String> recorrer = list.iterator();
   
    while (recorrer.hasNext())
    {
      String nombre = recorrer.next();
      if (nombre.equals("Barney")) {
        recorrer.remove();
      }else
      if(nombre != "Barney"){System.out.println(nombre);}/* Si no se incluye esta condición, pues también se imprimirá "Barney" puesto que la variable (nombre) hasta que
      no se inicie el siguiente ciclo, luego de la eliminación de "Barney" en la colección "list" mediante el Iterator "recorrer" tiene como valor "Barney"
     
      Esto es una solución alternativa para mostrar por pantalla los elementos de la colección, así que podrían considerarse otras opciones.*/
    }
    System.out.println("\nEsta colección ahora contiene: " + list.size() + " objetos." );
  }
}

Te recomiendo que lo analices y que realices diferentes pruebas, para que domines mas el tema.

Saludos!
« Última modificación: 29 de Septiembre 2014, 20:47 por Sniper »
while(estesVivo)
{
  aprende();
  ayuda();
  enseña();
}
if(mueres){teRecordaran();}

Susana83

  • Sin experiencia
  • *
  • Mensajes: 49
    • Ver Perfil
Re:ejercicio java
« Respuesta #4 en: 30 de Septiembre 2014, 13:10 »
Gracias Sniper!!!!! Has dado una explicacion muy detallada y clara y ya he entendido: hay que decir que elimine el objeto desde el iterator y no desde la lista pero esto no lo sabía  :-[ -- y estoy haciendo pruebas como me has recomendado gracias, gracias ,gracias

Jorge lopez

  • Sniper
  • Intermedio
  • ***
  • APR2.COM
  • Mensajes: 248
  • @SniperOfElite
    • Ver Perfil
Re:ejercicio java
« Respuesta #5 en: 30 de Septiembre 2014, 16:38 »
 Me alegro que te aya sido util Susana83, aprovecho para corregir algo que dije en esta ultima explicación:
Citar
para corregir esto usamos el método iterator de la clase Iterator
Corrección: El metodo iterator(); es un método del cual disponen las clases tipo colección, tales como List, ArrayList, CopyOnWriteArrayList, entre otras. Cuando se invoca este método sobre una colección de cuyo tipo es una colección que admita iterator(); pues el resultado es que este devuelve un tipo Iterator, y desde ese Iterator pues podemos usar los métodos disponibles para Iterator, hasNext(); next(); remove(); ext...

Espero no causarte confusión, mis disculpas por referir el método iterator(); como un método propio de la clase Iterator (incorrecto) ;D

Saludos!
while(estesVivo)
{
  aprende();
  ayuda();
  enseña();
}
if(mueres){teRecordaran();}

Susana83

  • Sin experiencia
  • *
  • Mensajes: 49
    • Ver Perfil
Re:ejercicio java
« Respuesta #6 en: 01 de Octubre 2014, 10:22 »
Son muchos detalles y es un poco enredado iterator (método) o Iterator (clase) es casi igual pero no es lo mismo, me lo apunto con un post it para no olvidarlo y gracias de nuevo

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".