Nota: Estou ciente do Iterator#remove()
método.
No exemplo de código a seguir, não entendo por que o método List.remove
in main
é lançado ConcurrentModificationException
, mas não no remove
método
public class RemoveListElementDemo {
private static final List<Integer> integerList;
static {
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
}
public static void remove(Integer toRemove) {
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
public static void main(String... args) {
remove(Integer.valueOf(2));
Integer toRemove = Integer.valueOf(3);
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
}
java
list
concurrentmodification
foreach
Bhesh Gurung
fonte
fonte
Iterator#remove()
. Por que você está fazendo assim?ConcurrentModificationException
e o outro não.return;
no loop.Respostas:
Eis o porquê: Como se diz no Javadoc:
Essa verificação é feita no
next()
método do iterador (como você pode ver no stacktrace). Mas chegaremos aonext()
método somente se forhasNext()
entregue true, que é o chamado pelo para cada um para verificar se o limite é atingido. No seu método remove, aohasNext()
verificar se ele precisa retornar outro elemento, verá que ele retornou dois elementos e, agora que um elemento foi removido, a lista contém apenas dois elementos. Então, tudo é pêssego e terminamos a iteração. A verificação de modificações simultâneas não ocorre, pois isso é feito nonext()
método que nunca é chamado.Em seguida, chegamos ao segundo loop. Após removermos o segundo número, o método hasNext verificará novamente se é possível retornar mais valores. Ele já retornou dois valores, mas a lista agora contém apenas um. Mas o código aqui é:
1! = 2, continuamos com o
next()
método, que agora percebe que alguém está mexendo com a lista e aciona a exceção.Espero que isso esclareça sua pergunta.
Resumo
List.remove()
não será lançadoConcurrentModificationException
quando remover o segundo último elemento da lista.fonte
Uma maneira de lidar com isso é remover algo de uma cópia de um
Collection
(não da própria coleção), se aplicável.Clone
a coleção original para fazer uma cópia via aConstructor
.Para o seu caso específico, primeiro, acho que não
final
é um caminho a percorrer, considerando que você pretende modificar a declaração anterior da listaConsidere também modificar uma cópia em vez da lista original.
fonte
O método de encaminhamento / iterador não funciona ao remover itens. Você pode remover o elemento sem erros, mas receberá um erro de tempo de execução ao tentar acessar os itens removidos. Você não pode usar o iterador porque, como mostra insistentemente, ele causará uma ConcurrentModificationException; portanto, use um loop for regular, mas retroceda nele.
Uma solução:
Atravesse a matriz na ordem inversa se você deseja remover um elemento da lista. Simplesmente, ao retroceder na lista, você evita visitar um item que foi removido, o que remove a exceção.
fonte
Esse trecho sempre lançará uma ConcurrentModificationException.
A regra é "Você não pode modificar (adicionar ou remover elementos da lista) enquanto itera sobre ela usando um Iterator (o que acontece quando você usa um loop para cada um)".
JavaDocs:
Os iteradores retornados pelos métodos iterator e listIterator dessa classe são rápidos: se a lista for modificada estruturalmente a qualquer momento após a criação do iterador, de qualquer forma, exceto pelos métodos de remoção ou adição do próprio iterador, o iterador lançará uma ConcurrentModificationException.
Portanto, se você deseja modificar a lista (ou qualquer coleção em geral), use o iterador, porque ele está ciente das modificações e, portanto, elas serão tratadas adequadamente.
Espero que isto ajude.
fonte
Eu tive o mesmo problema, mas no caso de adicionar um elemento en à lista iterada. Eu fiz assim
Agora tudo corre bem porque você não cria nenhum iterador sobre sua lista, mas itera-o "manualmente". E a condição
i < integerList.size()
nunca o enganará, porque quando você remove / adiciona algo ao tamanho da Lista do decremento / incremento da Lista.Espero que ajude, para mim isso foi solução.
fonte
Se você usar coleções de copiar na gravação, ele funcionará; no entanto, quando você usa list.iterator (), o Iterator retornado sempre fará referência à coleção de elementos como era quando (como abaixo) list.iterator () foi chamado, mesmo que outro thread modifique a coleção. Quaisquer métodos de mutação chamados em um Iterator ou ListIterator baseado em cópia na gravação (como adicionar, definir ou remover) lançarão uma UnsupportedOperationException.
fonte
Isso funciona bem no Java 1.6
~% javac RemoveListElementDemo.java
~% java RemoveListElementDemo
~% cat RemoveListElementDemo.java
~%
fonte
No meu caso, eu fiz assim:
fonte
Mudança Iterator
for each
parafor loop
resolver.E a razão é:
- Documentos Java referenciados.
fonte
Verifique o seu código man ....
No método principal, você está tentando remover o quarto elemento que não existe e, portanto, o erro. No método remove () você está tentando remover o terceiro elemento que existe e, portanto, nenhum erro.
fonte
2
e3
não são índices para a lista, mas elementos. A lógica de remoção verificaequals
os elementos da lista, não o índice dos elementos. Além disso, se fosse índice relacionado, seriaIndexOutOfBoundsException
, nãoConcurrentModificationException
.