Article image

CS

Cassio Santos31/07/2025 12:13
Compartilhe

Evitando ConcurrentModificationException ao Remover Elementos de uma Lista em Java

    Ao trabalhar com coleções em Java, especialmente listas, é comum a necessidade de remover elementos durante a iteração. No entanto, essa prática pode levar a uma exceção conhecida como ConcurrentModificationException. Este artigo explica por que isso acontece e apresenta abordagens seguras para evitar esse problema.

    O que é ConcurrentModificationException?

    ConcurrentModificationException é lançada quando uma coleção é modificada estruturalmente (elementos são adicionados ou removidos) enquanto está sendo iterada por métodos como for-each ou Iterator, exceto através dos métodos do próprio Iterator. Isso ocorre porque a estrutura interna da coleção muda durante a iteração, tornando o estado da iteração inconsistente.

    Exemplo do Problema

    Considere o seguinte código:

    List<String> nomes = new ArrayList<>();

    nomes.add("Alisson");

    nomes.add("Bruna");

    nomes.add("Cassio");

    for (String nome : nomes) {

      if (nome.equals("Bruna")) {

        nomes.remove(nome); // Lança ConcurrentModificationException

      }

    }

    Ao tentar remover "Bruna" durante o laço, a exceção será lançada.

    Abordagens para Evitar o Problema

    1. Usando uma Lista Auxiliar

    Uma abordagem segura é criar uma lista auxiliar para armazenar os elementos que devem ser removidos e, após a iteração, removê-los da lista original:

    List<String> nomesParaRemover = new ArrayList<>();

    for (String nome : nomes) {

      if (nome.equals("Bruna")) {

        nomesParaRemover.add(nome);

      }

    }

    nomes.removeAll(nomesParaRemover);

    2. Iterando Sobre uma Cópia da Lista

    Outra alternativa é criar uma cópia da lista e iterar sobre ela, removendo os elementos da lista original:

    List<String> copia = new ArrayList<>(nomes);

    for (String nome : copia) {

      if (nome.equals("Cassio")) {

        nomes.remove(nome);

      }

    }

    3. Usando o Iterator

    O uso explícito do Iterator permite remover elementos de forma segura durante a iteração:

    Iterator<String> iterator = nomes.iterator();

    while (iterator.hasNext()) {

      if (iterator.next().equals("Alisson")) {

        iterator.remove();

      }

    }

    Quando Usar Cada Abordagem?

    • Lista Auxiliar: Ideal quando deseja remover todos os elementos que atendem a uma condição.
    • Cópia da Lista: Útil quando a remoção é pontual ou quando a lógica exige iteração sobre o estado original.
    • Iterator: Recomendado para remoção durante a iteração, especialmente quando a performance é importante e não se deseja criar listas auxiliares.

    Conclusão

    Remover elementos de uma lista durante a iteração exige cuidado para evitar a ConcurrentModificationException. Escolher a abordagem correta depende do contexto da aplicação e da regra de negócio. Compreender essas técnicas é fundamental para escrever código Java robusto e seguro ao manipular coleções.

    Compartilhe
    Comentários (1)
    DIO Community
    DIO Community - 04/08/2025 11:42

    Excelente, Cassio! Seu artigo sobre "Evitando ConcurrentModificationException ao Remover Elementos de uma Lista em Java" é super claro e relevante. É fascinante ver como você aborda um problema comum que muitos desenvolvedores Java enfrentam, explicando por que a ConcurrentModificationException acontece e apresentando abordagens seguras para evitá-la.

    Você demonstrou que a exceção é lançada quando uma coleção é modificada durante a iteração, e apresentou três soluções eficazes: usar uma lista auxiliar, iterar sobre uma cópia da lista e usar o Iterator de forma explícita. Sua análise de quando usar cada abordagem, com exemplos práticos, é muito valiosa para qualquer um que busca escrever código Java robusto.

    Considerando que "o uso explícito do Iterator permite remover elementos de forma segura durante a iteração", qual você diria que é o maior benefício para um desenvolvedor ao utilizar o Iterator para remover um elemento de uma lista, em termos de eficiência e prevenção de bugs, em vez de usar um laço for-each para a remoção?