Publicado em

- 6 min read

Map e HashMap em Java: Entenda tudo sobre essa estrutura de dados

img of Map e HashMap em Java: Entenda tudo sobre essa estrutura de dados

Introdução

Nesse artigo, vamos conhecer o que é a interface Map e uma de suas implementações mais utilizadas: o HashMap. Detalheremos também como funcionam seus prinicipais métodos.

O que é um Map em Java?

A interface Map<K, V> representa uma estrutura de dados que mapeia chaves (keys - K) para valores (values - V). Diferente de listas ou conjuntos, um Map não armazena elementos isolados, mas sim pares associados: para cada chave, existe um único valor correspondente.

Essa estrutura é ideal quando você quer associar identificadores únicos (como nomes, códigos ou IDs) a dados relacionados, como idade, descrição ou objetos completos.

Estrutura do Map
Estrutura do Map

Representação gráfica

Imagine o cenário onde vamos armazenar a idade das pessoas em um mapa, internamente no Map ficaria assim:

   +-----------+------------------- +
|   Chave   |        Valor       |
+-----------+------------------- +
| "Ana"     |         25         |
| "Bruno"   |         32         |
| "Carlos"  |         32         |
+-----------+------------------- +

Essa estrutura funciona como uma tabela interna onde:

  • As chaves são únicas (não se repetem).
  • Os valores podem se repetir (duas pessoas podem ter a mesma idade, por exemplo).
  • É possível buscar rapidamente o valor associado a uma chave, como map.get(“Bruno”) → 32.

Mapas imutáveis

Alguns métodos estáticos permitem criar mapas imutáveis de forma prática. Esses mapas possuem as seguintes características:

  • Não podem ser modificados: não é possível adicionar, remover ou alterar chaves e valores — qualquer tentativa lança uma UnsupportedOperationException.
  • Não aceitam null como chave ou valor.
  • Rejeitam chaves duplicadas durante a criação, gerando uma IllegalArgumentException.
  • A ordem de iteração não é garantida e pode variar.

Map.of()

Através desse método estático, podemos criar um novo mapa imutável contendo no máximo 10 mapeamentos (pares de chave-valor):

   //Mapa de traduções
Map<String, String> dicionario = Map.of("cachorro", "dog", "gato", "cat");
System.out.println(dicionario);
//saída: {gato=cat, cachorro=dog}

Map.ofEntries()

Através desse método estático, podemos criar um novo mapa imutável a partir de entradas de chave-valor fornecidos:

   //Mapa de pontos de jogadores
Map<String, Integer> pontuacao = Map.ofEntries(
        Map.entry("Player_1", 100),
        Map.entry("Player_2", 124),
        Map.entry("Player_3", 50)
);
System.out.println(pontuacao);
//saída: {Player_3=50, Player_2=124, Player_1=100}

Map.copyOf()

Através desse método estático, criamos um novo mapa imutável contendo as entradas (pares de chave-valor) do mapa fornecido.

   //Cópia do mapa de pontuação de jogadores
Map<String, Integer> pontuacaoCopia = Map.copyOf(pontuacao);
System.out.println(pontuacaoCopia);
//saída: {Player_3=50, Player_2=124, Player_1=100}

Classe HashMap

É uma das implementações mais utilizadas da interface Map em Java, oferecendo uma combinação eficiente de performance, simplicidade e flexibilidade com as seguintes características:

  • Alto desempenho: fornece desempenho para operações simples de GET e PUT.
  • Permite null: aceita uma chave null e múltiplos valores null, o que não é possível em algumas outras implementações.
  • Não ordenado: não mantém a ordem de inserção das chaves.
  • É mutável: diferente dos mapas imutáveis, o HashMap permite adicionar, remover ou atualizar pares chave-valor.

construtor

Constrói um HashMap vazio. Para esse exemplo temos um mapa com chaves do tipo String e valores do tipo *Double, onde iremos armazenar temperaturas de cidades.

   //Mapa para a temperatura das cidades
Map<String, Double> temperaturas = new HashMap<>();

put()

Insere um novo par de chave-valor associando o valor especificado à chave especificada nesse mapa.

   temperaturas.put("São Paulo", 22.5);
temperaturas.put("Rio Grande do Sul", 9.0);
temperaturas.put("Pernambuco", 34.2);
temperaturas.put("Mato Grosso", 30.0);
System.out.println(temperaturas);
//saída: {Mato Grosso=30.0, Pernambuco=34.2, São Paulo=22.5, Rio Grande do Sul=9.0}

size()

Retorna o número de mapeamentos de chave-valor neste mapa.

   var numeroMapeamentos = temperaturas.size();
System.out.println(numeroMapeamentos);
//saída: 4

values()

Retorna uma coleção(Collection) dos valores contidos no mapa.

   var valoresMapeados = temperaturas.values();
System.out.println(valoresMapeados);
//saída: [30.0, 34.2, 22.5, 9.0]

keySet()

Retorna uma coleção(Set) das chaves contidas no mapa.

   var chavesMapeadas = temperaturas.keySet();
System.out.println(chavesMapeadas);
//saída: [Mato Grosso, Pernambuco, São Paulo, Rio Grande do Sul]

containsKey()

Podemos verificar se uma determinada chave existe no mapa. O método containsKey() retorna verdadeiro (true) se o mapa possuir o mapeamento com a chave especificada.

   var chaveExiste = temperaturas.containsKey("São Paulo");
System.out.println(chaveExiste);
//saída: true

containsValue()

Da mesma forma, podemos verificar se um determinado valor existe no mapa. O método containsValue() retorna verdadeiro (true) se o mapa possuir o mapeamento com o valor especificado.

   var valorExiste = temperaturas.containsValue(23.9);
System.out.println(valorExiste);
//saída: false

get()

Para recuperar um valor mapeado utilizamos o método get(). Caso o valor especificado não for encontrado, o retorno será null.

   var mapeamentoEncontrado = temperaturas.get("São Paulo");
System.out.println(mapeamentoEncontrado);
//saída: 22.5

var mapeamentoNaoEncontrado = temperaturas.get("Rio de Janeiro");
System.out.println(mapeamentoNaoEncontrado);
//saída: null

remove()

Para remover um mapeamento (par chave-valor), basta utilizar o método remove() especificando a chave do mapeamento.

   temperaturas.remove("Pernambuco");
System.out.println(temperaturas);
//saída: {Mato Grosso=30.0, São Paulo=22.5, Rio Grande do Sul=9.0}

computeIfPresente()

Utilizado para atualizar um valor associado a uma chave, somente se essa chave já existir no mapa e não for null. É um método interessante quando você precisa atualizar condicionalmente um valor existente, evitando utilizar métodos como containsKey() + put() deixando o código mais limpo e conciso.

   //Como Mato Grosso existe no mapa, somará 1.0 ao valor do mapeamento.
temperaturas.computeIfPresent("Mato Grosso", (chave, valor) -> valor + 1.0);
System.out.println(temperaturas.get("Mato Grosso"));
//saída: 31.0

computeIfAbsent()

Utilizado para adicionar um valor a uma chave no mapa somente se essa chave ainda não estiver presente (ou seja, não existir). Para casos onde o valor precisa ser calculado (sob demanda). É um método interessante, evitando utilizar métodos como containsKey() + put() deixando o código mais limpo e conciso.

   //Nesse caso, como Rio de Janeiro não existe no mapa, será inserido.
temperaturas.computeIfAbsent("Rio de Janeiro", chave -> 39.4 + 1);
System.out.println(temperaturas.get("Rio de Janeiro"));
//saída: 40.4

putIfAbsent()

Muito parecido com o método computeIfAbsent(), utilizado para adicionar um valor a uma chave no mapa somente se essa chave ainda não estiver presente (ou seja, não existir). Para casos onde o valor já está pronto. É um método interessante, evitando utilizar métodos como containsKey() + put() deixando o código mais limpo e conciso.

   temperaturas.putIfAbsent("Bahia", 37.6);
System.out.println(temperaturas.get("Bahia"));
//saída: 37.6

clear()

Remove todos os mapeamentos do mapa.

   temperaturas.clear();
System.out.println(temperaturas);
//saída: {}

isEmpty()

Retorna verdadeiro (true) se o mapa estiver vazio. Ou seja, não contiver mapeamentos de chave-valor.

   var mapeamentoVazio = temperaturas.isEmpty();
System.out.println(mapeamentoVazio);
//saída: true

Conclusão

Ao longo deste artigo, exploramos a interface Map em Java e vimos como ela é poderosa para representar estruturas de dados baseadas em chave e valor. Compreendemos desde sua definição até o uso prático de métodos essenciais como put, get, containsKey, computeIfPresent e computeIfAbsent.

Também conhecemos os mapas imutáveis com Map.of, Map.ofEntries e Map.copyOf, que oferecem alternativas seguras para situações onde não queremos permitir alterações após a criação.

Por fim, abordamos o HashMap, uma das implementações mais populares, graças à sua performance e simplicidade — sendo amplamente utilizado no dia a dia de quem desenvolve em Java.

Se você está começando agora ou reforçando conceitos, entender bem como usar Map é fundamental para escrever códigos mais limpos, eficientes e expressivos.

🔗 Repositório com os exemplos do artigo

Acesse o repositório com todos os exemplos prontos para rodar:
👉 https://github.com/LuizEduardoBilotta/demo—lebilotta-map

📚 Referências oficiais