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

9 respostas Resolvido
programaçãojava
L

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);   
  }

9 Respostas

L

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

A
Solucao aceita

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.

M

Solução extremamente elegante

R

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
R

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.

L

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”?

R

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!

P

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();
 }
A

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)

Criado 4 de abril de 2017
Ultima resposta 5 de abr. de 2017
Respostas 9
Participantes 6