Pregunta

Hola SO Guru, estoy teniendo un excelente trabajo con este código

public void kill(double GrowthRate, int Death)
{
    int before = population.size();
    for (PopulationMember p : population)
    {
        int[] probs = ProbablityArrayDeath(GrowthRate,Death,(int)p.fitness());
        if (probs[RandomNumberGen.nextRandomInt(0, 99)]==0)
        {
            population.remove(p);
        }
    }
    System.out.println("Intial Population: "+before+", Deaths:"+(before-          population.size())+", New Population: "+population.size());
}

Cuando ejecuto mi programa la primera vez que intenta ejecutar el código, aparece este error

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
    at java.util.HashMap$KeyIterator.next(HashMap.java:828)
    at Genetics.Population.kill(Population.java:181)
    at Genetics.Population.run(Population.java:47)
    at Control.Main.main(Main.java:35)

Habiendo mirado un poco esto parece ser un error que normalmente ocurre con los hilos por los que intentan acceder al mismo recurso al mismo tiempo, pero esto es lo que me hace no tener múltiples hilos en este sistema.

¿Alguien puede explicar por qué sucede esto o pensar en un truco para solucionarlo?

Muchas gracias ^ _ ^

¿Fue útil?

Solución

Puede modificar la Collection subyacente del Iterator (que está oculto en el bucle for-each ). La forma correcta de hacer esto es:

for (Iterator<PopulationMember> it = population.iterator(); it.hasNext();) {
    PopulationMemeber p = it.next();
    int[] probs = ProbablityArrayDeath(GrowthRate,Death,(int)p.fitness());
    if (probs[RandomNumberGen.nextRandomInt(0, 99)] == 0) {
        it.remove();
    }
}

Otros consejos

No puede utilizar el para cada bucle si elimina elementos de la colección.
Debe usar un Iterator y para eliminar el elemento actual llame a Iterator.remove .

De lo contrario, el iterador subyacente que el bucle for-each crea para usted detrás de escena no comprende cómo está cambiando la colección por la que está pasando, le dice que se está cambiando mientras lo itera.

Tienes un iterador sobre la población oculto bajo un bucle for. Está eliminando un elemento de la población en medio del trabajo del iterador. Iterator ya no puede funcionar porque cambiaste la colección en medio de la iteración.

No está relacionado con subprocesos múltiples.

Una solución alternativa puede ser copiar una colección. Iterar sobre la copia y eliminar elementos de la colección original.

public void kill(double GrowthRate, int Death) {
    int before = population.size();
    Collection<PopulationMember> forIteration = new HashSet<PopulationMember>(population); 
    for (PopulationMember p : forIteration) {
        int[] probs = ProbablityArrayDeath(GrowthRate,Death,(int)p.fitness());
        if (probs[RandomNumberGen.nextRandomInt(0, 99)]==0) {
            population.remove(p);
        }
    }
    System.out.println("Intial Population: "+before+", Deaths:"+(before - population.size())+", New Population: "+population.size());

}

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top