Removendo Itens de uma Coleção em Java

Ao trabalhar com coleções em Java, é comum precisar excluir elementos de uma lista que também aparecem em outra lista. Considere o seguinte cenário:

  • listaPrincipal contém: "A", "B", "C", "D", "E"
  • listaExclusao contém: "B", "F"

O objetivo é eliminar da listaPrincipal todos os itens presentes na listaExclusao.

Abordagem com loop aninhado — e o erro que surge

Uma tentativa inicial pode ser percorrer ambas as listas simultaneamente:

List<String> itensParaRemover = new ArrayList<>();
itensParaRemover.add("B");
itensParaRemover.add("F");

List<String> dados = new ArrayList<>();
dados.add("A");
dados.add("B");
dados.add("C");
dados.add("D");
dados.add("E");
dados.add("F");
dados.add("G");

for (String item : itensParaRemover) {
    for (String dado : dados) {
        if (item.equals(dado)) {
            dados.remove(dado);
        }
    }
}

Ao executar, o resultado é uma exceção:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
    at java.util.ArrayList$Itr.next(ArrayList.java:859)

Isso ocorre porque a lista está sendo modificada durante a iteração com for-each, o que viola as regras do iterador interno.

Resolução utilizando Iterator

A forma segura de remover elementos durante a iteração é empregando o Iterator explicitamente:

public static void main(String[] args) {
    List<String> itensParaRemover = new ArrayList<>();
    itensParaRemover.add("B");
    itensParaRemover.add("F");

    List<String> dados = new ArrayList<>();
    dados.add("A");
    dados.add("B");
    dados.add("C");
    dados.add("D");
    dados.add("E");
    dados.add("F");
    dados.add("G");

    Iterator<String> iterador = dados.iterator();
    for (String item : itensParaRemover) {
        while (iterador.hasNext()) {
            String elemento = iterador.next();
            if (elemento.equals(item)) {
                iterador.remove();
                break;
            }
        }
        iterador = dados.iterator();
    }

    for (String s : dados) {
        System.out.print(s + " ");
    }
}

Saída esperada:

A C D E G

Solução com Stream API (Java 8+)

A partir do Java 8, a API de streams oferece uma alternativa mais concisa e funcional:

public static void main(String[] args) {
    List<String> itensParaRemover = Arrays.asList("B", "F");

    List<String> dados = new ArrayList<>();
    dados.add("A");
    dados.add("B");
    dados.add("C");
    dados.add("D");
    dados.add("E");
    dados.add("F");
    dados.add("G");

    List<String> filtrados = dados.stream()
        .filter(elemento -> !itensParaRemover.contains(elemento))
        .collect(Collectors.toList());

    filtrados.forEach(s -> System.out.print(s + " "));
}

Resultado:

A C D E G

Nesta abordagem, o método filter mantém apenas os elementos que não estão na lista de exclusão. Note também o uso de Arrays.asList() para inicializar a coleção de forma simplificada, dispensando múltiplas chamadas ao método add().

Tags: java ArrayList Iterator Stream API ConcurrentModificationException

Publicado em 6-6 01:54 por Thomas