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:
listaPrincipalcontém: "A", "B", "C", "D", "E"listaExclusaoconté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().