---
title: "Como Usar HashMap em Zig"
url: "https://ziglang.com.br/receitas/como-usar-hashmap-em-zig/"
markdown_url: "https://ziglang.com.br/receitas/como-usar-hashmap-em-zig.MD"
description: "Aprenda a usar HashMap e StringHashMap em Zig para armazenar e recuperar dados por chave. Exemplos práticos com inserção, busca, remoção e iteração."
date: "2026-02-21"
author: "Zig Brasil"
---

# Como Usar HashMap em Zig

Aprenda a usar HashMap e StringHashMap em Zig para armazenar e recuperar dados por chave. Exemplos práticos com inserção, busca, remoção e iteração.


## Introdução

Um HashMap (também chamado de dicionário ou mapa) é uma estrutura de dados que associa chaves a valores, permitindo inserção, busca e remoção em tempo O(1) amortizado. Em Zig, a biblioteca padrão oferece `std.HashMap`, `std.AutoHashMap` e `std.StringHashMap` para diferentes tipos de chave.

Nesta receita, você aprenderá a usar essas estruturas para resolver problemas comuns do dia a dia.

## Pré-requisitos

- Zig instalado (versão 0.13+). Veja o [guia de instalação](/tutoriais/como-instalar-zig/)
- Conhecimento básico de Zig. Consulte a [introdução ao Zig](/tutoriais/introducao-ao-zig/)
- Familiaridade com [alocadores](/receitas/zig-general-purpose-allocator/)

## HashMap Básico com AutoHashMap

`AutoHashMap` detecta automaticamente a função de hash para o tipo da chave:

```zig
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // Criar HashMap de i32 -> []const u8
    var mapa = std.AutoHashMap(i32, []const u8).init(allocator);
    defer mapa.deinit();

    // Inserir pares chave-valor
    try mapa.put(1, "um");
    try mapa.put(2, "dois");
    try mapa.put(3, "três");
    try mapa.put(4, "quatro");

    // Buscar um valor
    if (mapa.get(2)) |valor| {
        std.debug.print("Chave 2: {s}\n", .{valor});
    }

    // Verificar se chave existe
    std.debug.print("Contém 3? {}\n", .{mapa.contains(3)});
    std.debug.print("Contém 5? {}\n", .{mapa.contains(5)});

    // Tamanho
    std.debug.print("Total de entradas: {d}\n", .{mapa.count()});
}
```

### Saída esperada

```
Chave 2: dois
Contém 3? true
Contém 5? false
Total de entradas: 4
```

## StringHashMap para Chaves de Texto

`StringHashMap` é otimizado para chaves do tipo `[]const u8`:

```zig
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var capitais = std.StringHashMap([]const u8).init(allocator);
    defer capitais.deinit();

    try capitais.put("Brasil", "Brasília");
    try capitais.put("Argentina", "Buenos Aires");
    try capitais.put("Chile", "Santiago");
    try capitais.put("Peru", "Lima");
    try capitais.put("Colômbia", "Bogotá");

    // Buscar
    const paises = [_][]const u8{ "Brasil", "Chile", "México" };
    for (&paises) |pais| {
        if (capitais.get(pais)) |capital| {
            std.debug.print("{s} -> {s}\n", .{ pais, capital });
        } else {
            std.debug.print("{s} -> não encontrado\n", .{pais});
        }
    }
}
```

## Iterar sobre um HashMap

```zig
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var estoque = std.StringHashMap(u32).init(allocator);
    defer estoque.deinit();

    try estoque.put("Teclado", 45);
    try estoque.put("Mouse", 120);
    try estoque.put("Monitor", 15);
    try estoque.put("Headset", 30);

    // Iterar sobre todas as entradas
    std.debug.print("=== Estoque ===\n", .{});
    var it = estoque.iterator();
    while (it.next()) |entry| {
        std.debug.print("  {s}: {d} unidades\n", .{ entry.key_ptr.*, entry.value_ptr.* });
    }

    // Iterar apenas sobre as chaves
    std.debug.print("\nProdutos: ", .{});
    var kit = estoque.keyIterator();
    while (kit.next()) |key_ptr| {
        std.debug.print("{s} ", .{key_ptr.*});
    }
    std.debug.print("\n", .{});
}
```

## Atualizar e Remover Entradas

```zig
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var pontuacao = std.StringHashMap(u32).init(allocator);
    defer pontuacao.deinit();

    try pontuacao.put("Alice", 100);
    try pontuacao.put("Bob", 85);
    try pontuacao.put("Carlos", 90);

    // Atualizar valor existente (put sobrescreve)
    try pontuacao.put("Bob", 95);

    // getOrPut: obtém existente ou insere novo
    const result = try pontuacao.getOrPut("Diana");
    if (!result.found_existing) {
        result.value_ptr.* = 0; // Valor padrão para nova entrada
    }
    std.debug.print("Diana: {d}\n", .{result.value_ptr.*});

    // Remover uma entrada
    const removido = pontuacao.fetchRemove("Carlos");
    if (removido) |kv| {
        std.debug.print("Removido Carlos com pontuação {d}\n", .{kv.value});
    }

    // Listar resultado final
    std.debug.print("\nPontuação final:\n", .{});
    var it = pontuacao.iterator();
    while (it.next()) |entry| {
        std.debug.print("  {s}: {d}\n", .{ entry.key_ptr.*, entry.value_ptr.* });
    }
}
```

## Exemplo Prático: Contar Frequência de Palavras

```zig
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const texto = "zig é rápido zig é seguro zig é incrível zig zig zig";

    var frequencia = std.StringHashMap(u32).init(allocator);
    defer frequencia.deinit();

    // Contar palavras
    var palavras = std.mem.tokenizeAny(u8, texto, " ");
    while (palavras.next()) |palavra| {
        const result = try frequencia.getOrPut(palavra);
        if (result.found_existing) {
            result.value_ptr.* += 1;
        } else {
            result.value_ptr.* = 1;
        }
    }

    // Exibir frequência
    std.debug.print("Frequência de palavras:\n", .{});
    var it = frequencia.iterator();
    while (it.next()) |entry| {
        std.debug.print("  \"{s}\": {d}x\n", .{ entry.key_ptr.*, entry.value_ptr.* });
    }
    std.debug.print("Palavras distintas: {d}\n", .{frequencia.count()});
}
```

## HashMap com Valores Complexos

```zig
const std = @import("std");

const Produto = struct {
    nome: []const u8,
    preco: f64,
    estoque: u32,
};

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var catalogo = std.StringHashMap(Produto).init(allocator);
    defer catalogo.deinit();

    try catalogo.put("SKU001", .{ .nome = "Teclado Mecânico", .preco = 299.90, .estoque = 45 });
    try catalogo.put("SKU002", .{ .nome = "Mouse Gamer", .preco = 159.90, .estoque = 120 });
    try catalogo.put("SKU003", .{ .nome = "Monitor 4K", .preco = 2499.00, .estoque = 8 });

    // Buscar produto
    if (catalogo.get("SKU002")) |produto| {
        std.debug.print("Produto: {s}\n", .{produto.nome});
        std.debug.print("Preço: R$ {d:.2}\n", .{produto.preco});
        std.debug.print("Estoque: {d}\n", .{produto.estoque});
    }

    // Calcular valor total do estoque
    var valor_total: f64 = 0;
    var it = catalogo.iterator();
    while (it.next()) |entry| {
        const p = entry.value_ptr.*;
        valor_total += p.preco * @as(f64, @floatFromInt(p.estoque));
    }
    std.debug.print("\nValor total em estoque: R$ {d:.2}\n", .{valor_total});
}
```

## Dicas e Boas Práticas

1. **Escolha o tipo certo**: Use `StringHashMap` para chaves de texto, `AutoHashMap` para tipos primitivos.

2. **Use `getOrPut`**: Para padrões de "inserir se não existe", `getOrPut` é mais eficiente que verificar e inserir separadamente.

3. **Cuidado com referências**: As chaves e valores são copiados no HashMap. Strings (`[]const u8`) são ponteiros, então garanta que os dados originais permaneçam válidos.

4. **Pré-aloque com `ensureTotalCapacity`**: Se você sabe quantas entradas terá, pré-alocar evita realocações durante a inserção.

5. **Sempre libere**: Use `defer mapa.deinit()` logo após a criação.

## Receitas Relacionadas

- [Arrays Dinâmicos com ArrayList](/receitas/zig-arraylist-dinamico/) - Listas dinâmicas
- [Conjunto (Set) de Valores Únicos](/receitas/zig-set-conjunto/) - Sets baseados em HashMap
- [Usando GeneralPurposeAllocator](/receitas/zig-general-purpose-allocator/) - Alocador de memória
- [Como parsear JSON em Zig](/receitas/zig-parse-json/) - JSON para HashMap

## Tutoriais Relacionados

- [Structs, Enums e Unions em Zig](/tutoriais/structs-enums-unions-zig/)
- [Gerenciamento de Memória em Zig](/tutoriais/gerenciamento-de-memoria-zig/)
