Um Map armazena pares chave-valor
Um HashMap (de java.util) armazena associações: cada chave é mapeada para um valor, e você busca os valores pela chave em tempo aproximadamente constante. Pense em um dicionário: a palavra é a chave e a definição é o valor.
Os dois parâmetros de tipo são <KeyType, ValueType>. Aqui as chaves são String e os valores são Integer. Assim como com ArrayList, você normalmente declara a variável com o tipo da interface Map e constrói um HashMap.
put, get e sobrescrita
Duas coisas para internalizar:
- Uma chave é única.
putcom uma chave existente substitui o valor dela e retorna o antigo. getem uma chave inexistente retornanull, não um erro. Fazer o auto-unboxing dessenullpara umintlança umaNullPointerException, uma fonte comum de bugs.
getOrDefault evita a armadilha do null
Em vez de verificar null toda vez, peça um valor padrão:
Essa é a maneira mais limpa de lidar com buscas de itens "talvez presentes", e leva diretamente ao padrão mais famoso de HashMap.
Contar ocorrências
Contar quantas vezes cada item aparece é a tarefa clássica de um HashMap:
O padrão map.put(key, map.getOrDefault(key, 0) + 1) se lê como "pegue a contagem atual (ou zero), some um e guarde de volta". Um equivalente mais elegante é counts.merge(word, 1, Integer::sum).
Verificar e remover
putIfAbsent(key, value) só escreve quando a chave não existe, útil para inicialização preguiçosa.
Percorrer um HashMap
O laço mais comum percorre entrySet(), fornecendo cada chave e valor juntos:
Se você precisa apenas das chaves ou apenas dos valores:
Você também pode usar forEach com uma lambda: ages.forEach((name, age) -> System.out.println(name + ": " + age));.
O HashMap não mantém a ordem
Um HashMap não garante nenhuma ordem de iteração: é a que o hashing produz, e ela pode mudar entre execuções. Se você precisa de uma ordem previsível:
LinkedHashMappreserva a ordem de inserção.TreeMapmantém as chaves ordenadas pela ordem natural (ou por umComparatorque você fornecer).
As três implementam a interface Map, então trocar entre elas é uma alteração de uma única linha no construtor.
As chaves precisam ser hasheáveis
HashMap encontra as entradas fazendo o hash da chave, então o hashCode() e o equals() de uma chave precisam ser consistentes entre si. Tipos nativos como String e Integer já fazem isso corretamente. Se você usar sua própria classe como chave, sobrescreva tanto equals quanto hashCode; caso contrário, dois objetos que são "iguais" em significado vão parar em buckets diferentes e suas buscas vão falhar de forma misteriosa.
A seguir: HashSet
Um HashMap responde "qual valor está armazenado sob esta chave?". Quando você só se importa se algo está presente ou não (um conjunto de valores únicos, sem dados associados), a ferramenta é HashSet, que vem a seguir.
Perguntas frequentes
Como criar um HashMap em Java?
Declare-o com dois parâmetros de tipo (o tipo da chave e o tipo do valor) e chame o construtor: Map<String, Integer> ages = new HashMap<>();. Depois adicione entradas com ages.put("Ada", 36); e leia-as com ages.get("Ada");. Importe java.util.HashMap e java.util.Map.
Como percorrer um HashMap em Java?
Itere sobre map.entrySet() com um laço for-each para obter cada chave e valor juntos: for (Map.Entry<String, Integer> e : map.entrySet()) { ... }, lendo e.getKey() e e.getValue(). Você também pode percorrer map.keySet() para obter só as chaves ou map.values() para obter só os valores. Lembre-se de que um HashMap não mantém a ordem de inserção.
Qual é a diferença entre get e getOrDefault?
get(key) retorna o valor de uma chave, ou null se a chave não existir, o que pode causar uma NullPointerException se você usar o resultado diretamente. getOrDefault(key, fallback) retorna o valor se estiver presente; caso contrário, retorna o valor padrão que você passar, evitando a verificação de null. É especialmente útil para contagem: counts.put(c, counts.getOrDefault(c, 0) + 1).