Duda con Iteradores en Java

Meleagant

Estoy programando una aplicación en la que tengo un ArrayList<Objeto> que utilizo para repartir tareas entre los distintos objetos.

Para ello la aplicación tiene un método private Objeto escogerObjeto() que devuelve un Objeto elegido de acuerdo a sus criterios.

Por el momento el único criterio que quiero seguir es escoger el Objeto siguiente.

El código, por tanto, me queda así:

	private Objeto escogerObjeto(){
		
	if(objIt.hasNext()){
		return objIt.next();
	}
	else{
		objIt = objetos.iterator();
		return objIt.next();
	}

}

Que básicamente lo que hace es devolver el siguiente objeto de la lista o, si el iterador ha llegado a la ultima posición, reiniciarlo y devolver el primer objeto.

Cada vez que ejecuto el código llega a la primera condición, la cumple, entra en el if y me devuelve una excepción ConcurrentModificationException, pero por más que miro el código (que es bien simplón) no veo cómo puede estar produciéndose un acceso concurrente.

No hay distintos threads que puedan estar ejecutando la instrucción al mismo tiempo.

¿Alguna idea?

mry00

Si cambias el ArrayList por CopyOnWriteArrayList creo que funciona

1 1 respuesta
Meleagant

#2 Perfecto, utilizando ese tipo de lista funciona. Muchas gracias :)

Por lo que leo en la documentación, la CopyOnWriteArrayList simplemente impide que se hagan modificaciones sobre los objetos de la lista desde el iterador.

Lo que no acabo de entender es por qué me saltaba el error con la otra clase, si no había ningún acceso concurrente, de hecho en otra parte de la aplicación utilizo un iterador que hace lo siguiente sobre un ArrayList:

	while(itNegativas.hasNext()){
			
		n = itNegativas.next();
		...
		if(...){
			...
			itNegativas.remove();
		}
		
	}

Y no da ningún problema de concurrencia.

MTX_Anubis

La excepción de Concurrent es un poco estafa (porque no quiere decir que sea concurrente por lo que normalmente entendemos xD).

Si has modificado la lista del iterador después de haber creado un iterador, en el próximo next() del iterador te saltará la excepción (las listas tienen una variable que cuenta las modificaciones sobre ella y el iterador se guarda ese numero cuando se crea, si cuando intenta sacar un elemento nuevo los números no coinciden, zasca...)

Quizá estás modificando la lista después de haber sacado el iterador y luego has llamado a ese método.

1 respuesta
Meleagant

#4 Pues no digas más.

El iterador lo había creado en el constructor de la clase, y a la clase se le van añadiendo desde fuera objetos a la lista. Lo que no quiero es que el iterador se construya después de añadir cada objeto a la lista, porque entonces no me sirve como "cursor" fijo de la posición en la que me encuentro.

Quizá deba usar otro tipo de estructura para este caso concreto.

Muchas gracias a los dos :)

MTX_Anubis

Entonces utiliza el ListIterator en vez del Iterator y añade los elementos a través de él :P

1 1 respuesta
elkaoD

#6 primera noticia de que ListIterator hace las listas iteradas mutables. Un poco peligroso, pero awesome usado con cabeza.

1 respuesta
MTX_Anubis

#7 Realmente creo que depende de la lista. A mí me suena haberlo usado con ArrayList sin problemas, quizá en otras implementaciones distintas te salte excepción (maravillas de este lenguaje... xD).

Usuarios habituales

  • MTX_Anubis
  • elkaoD
  • Meleagant
  • mry00