HashMap em Java: 5 erros fatais ao percorrer e como evitá-los

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: HashMap — amigo ou inimigo?



Todo desenvolvedor Java, mais cedo ou mais tarde, se depara com HashMap. Esta é, provavelmente, a implementação mais popular da interface Map em Java. Mas eis o paradoxo: todos sabem como colocar um elemento no mapa, mas quando se trata de percorrê-lo (iteração), começa o verdadeiro caos. A pergunta "Iterate through a HashMap" no Stack Overflow acumulou milhares de visualizações, e a quantidade de erros em projetos reais é alarmante.



Neste artigo, analisaremos 5 erros mais perigosos ao percorrer um HashMap em Java, que podem levar à queda da aplicação, perda de dados e código ilegível. Você aprenderá não apenas como fazer errado, mas também receberá padrões funcionais para cada caso. Vamos lá!



Erro nº1: ConcurrentModificationException — "Removendo em plena execução"



Qual é o problema?

O erro mais clássico. Você itera sobre um HashMap e tenta remover um elemento usando map.remove(key). Em 90% dos casos, isso resulta em ConcurrentModificationException.



// ❌ PERIGOSO: causará exceção!HashMap<String, Integer> scores = new HashMap<>();scores.put("Alice", 90);scores.put("Bob", 50);scores.put("Charlie", 70);

for (String name : scores.keySet()) { if (scores.get(name) < 60) { scores.remove(name); // ConcurrentModificationException! }}


Por que isso acontece?

O iterador interno do HashMap mantém um contador de modificações (modCount). Quando você remove um elemento diretamente pela coleção, o contador muda, mas o iterador não sabe disso. Na próxima iteração, ele verifica: "Ei, o contador não corresponde! Vamos lançar a exceção".



Como corrigir?

Use o Iterator com seu método remove():



// ✅ CORRETO: usando IteratorHashMap<String, Integer> scores = new HashMap<>();scores.put("Alice", 90);scores.put("Bob", 50);scores.put("Charlie", 70);

Iterator<Map.Entry<String, Integer>> iterator = scores.entrySet().iterator();while (iterator.hasNext()) { Map.Entry<String, Integer> entry = iterator.next(); if (entry.getValue() < 60) { iterator.remove(); // Remoção segura! }}


Com Java 8, surgiu uma forma ainda mais elegante — removeIf():



// ✅ AINDA MELHOR: removeIf (Java 8+)scores.entrySet().removeIf(entry -> entry.getValue() < 60);


Erro nº2: Percorrer lentamente com keySet() e get()



Qual é o problema?

Muitos iniciantes fazem assim:



// ❌ LENTO: keySet() + get() — busca duplafor (String key : map.keySet()) {    System.out.println("Key: " + key + ", Value: " + map.get(key));}


À primeira vista, funciona. Mas o problema é que map.get(key) internamente procura o hash novamente e percorre o bucket. A cada iteração do loop, você faz duas chamadas ao HashMap em vez de uma. Para mapas pequenos, isso é imperceptível, mas com centenas de milhares de registros, é uma perda de desempenho de até 30-40%.



Como corrigir?

Sempre use entrySet() — ele retorna pares "chave-valor" em uma única passagem:



// ✅ RÁPIDO: entrySet() — uma passagemfor (Map.Entry<String, Integer> entry : map.entrySet()) {    System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());}


Ou use forEach com Java 8:



// ✅ CONCISO: forEach (Java 8+)map.forEach((key, value) -> {    System.out.println("Key: " + key + ", Value: " + value);});


Erro nº3: Confusão com a ordem dos elementos



Qual é o problema?

Você escreveu um código que percorre um HashMap e espera que os elementos estejam na ordem de inserção. Mas obtém uma sequência completamente diferente. Isso leva a bugs que

Blogs

Book Recommendations