questions interview example collection colecciones java collections

interview - Java: ConcurrentModificationException mientras se itera sobre la lista



java list (3)

Cuando ejecuto el siguiente código, obtengo ConcurrentModificationException

Collection<String> myCollection = Collections.synchronizedList(new ArrayList<String>(10)); myCollection.add("123"); myCollection.add("456"); myCollection.add("789"); for (Iterator it = myCollection.iterator(); it.hasNext();) { String myObject = (String)it.next(); System.out.println(myObject); myCollection.remove(myObject); //it.remove(); }

¿Por qué recibo la excepción, aunque estoy usando Collections.synchronizedList?

Cuando cambio myCollection a

ConcurrentLinkedQueue<String> myCollection = new ConcurrentLinkedQueue<String>();

No entiendo esa excepción.

¿Cómo es ConcurrentLinkedQueue en java.util.concurrent diferente de Collections.synchronizedList?


¿Cómo es ConcurrentLinkedQueue en java.util.concurrent diferente de Collections.synchronizedList?

Tienen implementaciones diferentes y, por lo tanto, pueden elegir lanzar ConcurrentModificationException o manejar la situación que describa con elegancia. Evidentemente CLQ maneja con gracia, y ArrayList envuelto por Collections.synchronizedList (mi conjetura es que el comportamiento es ArrayList, no el de la envoltura) no.

Como dice @unbeli, elimine a través del iterador, no la colección mientras itera.


Una lista sincronizada no proporcionará una nueva implementación de Iterator . Utilizará la implementación de la lista sincronizada . La implementación de iterator() es:

public Iterator<E> iterator() { return c.iterator(); // Must be manually synched by user! }

De ArrayList :

Los iteradores devueltos por el iterador de esta clase y los métodos listIterator son rápidos : si la lista se modifica estructuralmente en cualquier momento después de que se crea el iterador, de cualquier forma excepto a través de los propios métodos remove o add del iterador, el iterador generará una ConcurrentModificationException

Desde ConcurrentLinkedQueue#iterator :

Devuelve un iterador sobre los elementos en esta cola en la secuencia correcta. El iterador devuelto es un iterador "débilmente consistente" que nunca arrojará ConcurrentModificationException , y garantiza que atravesará los elementos tal como existían en la construcción del iterador, y puede (pero no se garantiza que) reflejar cualquier modificación posterior a la construcción.

Los iteradores devueltos por las dos colecciones son diferentes por diseño .


no hagas

myCollection.remove(myObject);

hacer

it.remove();

No hay necesidad de sincronización o recopilación concurrente