Pergunta

im Hey SO Guru ter um pedaço de um trabalho com 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());
}

Quando eu executar o meu programa na primeira vez que tenta executar o código que atinge este erro

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)

Tendo arregalou os olhos em torno de um pouco este parece ser um erro que normalmente acontece com as linhas por que eles tentam e acessar o mesmo recurso simultaneamente, mas isso é o que ficar me im não multithreading em todo este sistema.

Alguém pode explicar por que isso está acontecendo, ou pensar em um hack para contornar o problema

Muito obrigado ^ _ ^

Foi útil?

Solução

Você pode modificar o Collection subjacente da Iterator (que está escondido no circuito for-each). A maneira correta de fazer isso é:

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();
    }
}

Outras dicas

Você não pode usar o loop for each se você remover coisas da coleção.
Você tem que usar um Iterator e para remover o Iterator.remove chamada item atual.

Caso contrário, o subjacente iterador que o para-cada loop cria para você nos bastidores não compreende como é que a coleção está atravessando está mudando, diz-lhe que ele está sendo alterado enquanto você iterar-lo.

Você tem um iterador sobre população escondida sob um loop. Você está removendo um item da população no meio do iterador de trabalho. Iterator não pode mais trabalhar, porque você mudou a coleção no meio dela iteração.

Não é relacionada com multithreading.

Uma solução pode ser copiar uma coleção. Iterar sobre os elementos de cópia e remover da coleção 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top