Como remover dados de um hashMap em tempo de execução

Oi, eu sei que quando eu modifico um hashmap em tempo de execução ele da um erro de: java.util.ConcurrentModificationException.
então como eu faria para remover um determinado registro, pq teoricamente se eu quero fazer algo é necessario informar a chave, mas eu posso informar a chave para apagar a propria chave ? ._.
caso tenha ficado confuso :sweat_smile: eu apenas quero remover registros em tempo de execução usando uma estrutura de repetição :smile:

for(Object key: list.keySet()){
          
      Object value = list.remove(key);    
      System.out.println("Valor: " + value);   
  }

Não entendi exatamente a questão, mas, se foi o que eu entendi, você pode sim remover, inclusive, a classe HashMap possui um método chamado remove, conform consta no javadoc da mesma

Esse erro acontece quando você tenta remover um elemento de uma collection, enquanto percorre essa collection usando um iterator.

No seu caso, você tá percorrendo a collection “list.keySet()” que é um Set com todas as keys do mapa.
Quando você usa esse for, o java está por baixo dos panos chamando um iterator para isso.
Quando você chama o remove do Map, ele também precisa remove do set com todas as keys, e cai na condiçao que citei acima.

Um maneira rápida de evitar isso no seu código, é percorrer uma cópia do keySet original. Assim você pode manipular o original tranquilamente:

for(Object key:  new HashSet<>(list.keySet()) ){
      Object value = list.remove(key);    
      System.out.println("Valor: " + value);   
  }

O new HashSet lá vai criar a cópia que falei.

2 curtidas

Solução extremamente elegante

O problema é que você está tentando remover um índice ao qual está sendo utilizado como recurso do loop. Para não ter problemas de integridade e outros, o Java não permite vc fazer este tipo de operação desta forma. Isto ocorre com as Maps e Lists da vida.
A solução de contorno é criar uma hash de excluídos externo ao loop em questão e após a conclusão do loop remover os índices da hasmap originial com base na de excluídos. Outro ponto de sugestão é trabalhar com o entrySet() ao invés do keySet(), pois existe um impacto de desempenho entre eles. Segue um exemplo básico de como fazer que com certeza merecerá ser evoluído…rs

Map<Integer, String> list = new HashMap();
list.put(1, "Banana");
list.put(2, "Maça");
list.put(3, "Pera");
list.put(4, "Uva");

Map<Integer, String> removidos = new HashMap();

for(Map.Entry entry : list.entrySet()){
	if("Banana".equals(entry.getValue().toString()) ||
			"Uva".equals(entry.getValue().toString())){
		removidos.put((Integer)entry.getKey(), entry.getValue().toString());
	}
}

// VALIDANDO FRUTAS PARA REMOÇÃO

for(Map.Entry key : removidos.entrySet()){
	System.out.println("Removendo o item: " + key.getValue());
}

// REMOVENDO AS FRUTAS

for(Map.Entry entry : removidos.entrySet()){
	list.remove(entry.getKey());
}

// VALIADNDO A LISTA ORIGINAL SEM AS FRUTAS REMOVIDAS
System.out.println("## LISTA ORIGINAL ##");
for(Map.Entry key : list.entrySet()){
	System.out.println(key.getValue());
}

Saída do console:

Removendo o item: Banana
Removendo o item: Uva
## LISTA ORIGINAL ##
Maça
Pera
1 curtida

Ah, é importante saber que essa alteração é válida se vc não tiver elementos com a mesma chave no Map, pois o entrySet() retorna um conjunto de dados sem valores repetidos.

Em que situações é possível ter mais de um elemento com a mesma chave no mapa?
Se eu faço

Map<Integer, String> mapa = new HashMap<Integer, String>();
mapa.put(1, "João");
mapa.put(1, "Anselmo");

Eu não tenho um mapa com uma posição cuja chave é 1 e o valor é “Anselmo”?

Você tem razão!!! Comi bola na explicação. O map atualiza o índice com base na última inserção. Em outros casos de Hashes faz mais sentido. Obrigado pela correção!

Se usares explicitamente um iterator podes remover diretamente no ciclo.

 Iterator it =  map.keySet().iterator();

 while(it.hasNext()) {
     Object key=it.next();
     System.out.println("Valor: " + list.get(key));   
     it.remove();
 }
1 curtida

Exato.

Eu nao tinha certeza o que aconteceria com o valor alocado no mapa se você só removesse a key.

Quando tive a chance, eu notei que o Set do map é uma classe específica que remove o par inteiro (key, value) e nao apenas a key, sendo uma boa alternativa.

Mas como soluçao melhor, com Java 8, eu prefiro usar o map.keySet().removeIf(pred)