prevent - set java util concurrentmodificationexception




Pourquoi List.addAll d'une sous-liste inversée de la liste provoque-t-il une exception ConcurrentModificationException (3)

La question se trouve ici à ArrayList#checkForComodification

private void checkForComodification() {
    if (ArrayList.this.modCount != this.modCount)
        throw new ConcurrentModificationException();
    }
}

Toutefois, dans ce cas particulier, vous n'avez pas besoin de rajouter manuellement une sous-liste inversée, car la réversion est effectuée sur la liste d' origine . Donc, tout ce dont vous avez besoin est juste de laisser tomber

list.removeAll(...);
list.addAll(...);

et ne laissez que ce code:

List<Integer> toReverse = list.subList(startIndex, endIndex+1);
Collections.reverse(toReverse);

J'ai essayé de prendre une liste secondaire , de l'inverser et de replacer la liste reversed à la position de départ. Par exemple, supposons que nous ayons la liste [1, 2, 3, 4, 5, 6] , puis inverser l'index 2 à l'index 4 donnerait [1, 2, 5, 4, 3, 6] .

J'ai écrit du code pour cela, mais il donne à chaque fois une ConcurrentModificationException (sauf si startIndex == endIndex). Un exemple reproductible minimum est fourni ci-dessous:

int startIndex = 2;
int endIndex = 4;
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);

List<Integer> toReverse = list.subList(startIndex, endIndex+1);
Collections.reverse(toReverse);
list.removeAll(toReverse);
list.addAll(startIndex, toReverse);

Exception dans le thread "principal" java.util.ConcurrentModificationException
à java.util.ArrayList $ SubList.checkForComodification (Source inconnue)
à java.util.ArrayList $ SubList.size (Source inconnue) à
java.util.AbstractCollection.toArray (Source inconnue) sur
java.util.ArrayList.addAll (Source inconnue) sur
test.ConcurrentExample.main (ConcurrentExample.java:64)

La ligne réelle à laquelle l'erreur fait référence est list.addAll(startIndex, toReverse); .

Je ne suis pas sûr de la nature du problème, car rien ne semble avoir été modifié au cours d'une itération. Si quelqu'un pouvait expliquer pourquoi cela se produit et / ou comment y remédier, cela serait grandement apprécié.


List.subList renvoie une vue en direct de la liste entre les éléments spécifiés, et non une copie de ces éléments (voir la documentation ). Par conséquent, l'ajout à la liste d'origine modifiera également la sous-liste, ce qui conduira à ConcurrentModificationException (puisque ce qui est ajouté et à ce que vous ajoutez sont également modifiés en même temps).

list.subList(startIndex, endIndex+1)

Vous pouvez corriger un code en copiant la liste, comme

List<Integer> toReverse = new ArrayList<>(list.subList(startIndex, endIndex+1));

Parmi les suggestions de helospark & Nir Levy , utilisez sauter et limiter dans Stream

List<Integer> toReverse = list.stream() //
                .skip(startIndex) //
                .limit(endIndex + 1) //
                .collect(Collectors.toList());




concurrentmodification