O HashMap é uma das estruturas de dados mais úteis em Rust. Ele armazena pares chave-valor com busca em tempo O(1) amortizado, sendo ideal para caches, contadores, índices e mapeamentos em geral. Nesta receita, você vai aprender a criar, inserir, buscar, atualizar e iterar sobre HashMaps com exemplos completos e executáveis.
Dependências
O HashMap faz parte da biblioteca padrão. Não é necessário adicionar nada ao Cargo.toml:
[package]
name = "receita-hashmap"
version = "0.1.0"
edition = "2021"
Código Completo
use std::collections::HashMap;
fn main() {
// =============================================
// 1. Criando um HashMap
// =============================================
let mut notas: HashMap<String, f64> = HashMap::new();
// Criar a partir de um array de tuplas
let capitais = HashMap::from([
("Brasil", "Brasília"),
("Argentina", "Buenos Aires"),
("Chile", "Santiago"),
]);
// Criar a partir de dois iteradores com zip + collect
let chaves = vec!["um", "dois", "três"];
let valores = vec![1, 2, 3];
let mapa: HashMap<&str, i32> = chaves.into_iter().zip(valores).collect();
println!("Mapa criado com zip: {:?}", mapa);
// =============================================
// 2. Inserindo valores
// =============================================
notas.insert("Maria".to_string(), 9.5);
notas.insert("João".to_string(), 8.0);
notas.insert("Ana".to_string(), 10.0);
notas.insert("Carlos".to_string(), 7.5);
// insert() retorna Option com o valor anterior (se existia)
let anterior = notas.insert("João".to_string(), 8.5);
println!("Nota anterior do João: {:?}", anterior); // Some(8.0)
// =============================================
// 3. Buscando valores com get()
// =============================================
// get() retorna Option<&V>
if let Some(nota) = notas.get("Maria") {
println!("Nota da Maria: {}", nota);
}
// get() com chave inexistente retorna None
match notas.get("Pedro") {
Some(nota) => println!("Nota do Pedro: {}", nota),
None => println!("Pedro não encontrado"),
}
// contains_key() verifica se a chave existe
println!("Ana está no mapa? {}", notas.contains_key("Ana"));
// =============================================
// 4. Entry API — inserir ou atualizar
// =============================================
// or_insert: insere valor padrão se a chave não existe
notas.entry("Pedro".to_string()).or_insert(6.0);
println!("Nota do Pedro (inserida): {}", notas["Pedro"]);
// or_insert_with: insere resultado de closure se não existe
notas.entry("Lucas".to_string()).or_insert_with(|| {
println!("Calculando nota padrão para Lucas...");
5.0
});
// Atualizar valor existente via Entry API
notas.entry("Maria".to_string())
.and_modify(|nota| *nota += 0.5)
.or_insert(0.0);
println!("Nota da Maria atualizada: {}", notas["Maria"]);
// =============================================
// 5. Iterando sobre o HashMap
// =============================================
println!("\n--- Todas as notas ---");
for (nome, nota) in ¬as {
println!("{}: {:.1}", nome, nota);
}
// Iterando apenas sobre chaves
print!("Alunos: ");
for nome in notas.keys() {
print!("{} ", nome);
}
println!();
// Iterando apenas sobre valores
let media: f64 = notas.values().sum::<f64>() / notas.len() as f64;
println!("Média da turma: {:.2}", media);
// =============================================
// 6. Removendo entradas
// =============================================
let removido = notas.remove("Carlos");
println!("\nRemovido Carlos: {:?}", removido); // Some(7.5)
// =============================================
// 7. Exemplo prático: contagem de palavras
// =============================================
let texto = "rust é rápido rust é seguro rust é divertido aprender rust";
let mut contagem: HashMap<&str, usize> = HashMap::new();
for palavra in texto.split_whitespace() {
*contagem.entry(palavra).or_insert(0) += 1;
}
println!("\n--- Contagem de palavras ---");
// Ordenar por frequência (maior para menor)
let mut palavras: Vec<(&&str, &usize)> = contagem.iter().collect();
palavras.sort_by(|a, b| b.1.cmp(a.1));
for (palavra, freq) in palavras {
println!("{}: {}", palavra, freq);
}
// =============================================
// 8. HashMap com tipos customizados como chave
// =============================================
#[derive(Debug, PartialEq, Eq, Hash)]
struct Coordenada {
x: i32,
y: i32,
}
let mut grid: HashMap<Coordenada, &str> = HashMap::new();
grid.insert(Coordenada { x: 0, y: 0 }, "origem");
grid.insert(Coordenada { x: 1, y: 2 }, "ponto A");
if let Some(local) = grid.get(&Coordenada { x: 0, y: 0 }) {
println!("\n(0,0) = {}", local);
}
// Informações úteis
println!("\nCapitais: {:?}", capitais);
println!("Total de alunos: {}", notas.len());
println!("Mapa vazio? {}", notas.is_empty());
}
Saída do Programa
Mapa criado com zip: {"um": 1, "dois": 2, "três": 3}
Nota anterior do João: Some(8.0)
Nota da Maria: 9.5
Pedro não encontrado
Ana está no mapa? true
Nota do Pedro (inserida): 6.0
Calculando nota padrão para Lucas...
Nota da Maria atualizada: 10.0
--- Todas as notas ---
Maria: 10.0
João: 8.5
Ana: 10.0
Pedro: 6.0
Lucas: 5.0
Alunos: Maria João Ana Pedro Lucas
Média da turma: 7.90
Removido Carlos: Some(7.5)
--- Contagem de palavras ---
rust: 4
é: 3
rápido: 1
seguro: 1
divertido: 1
aprender: 1
(0,0) = origem
Capitais: {"Brasil": "Brasília", "Argentina": "Buenos Aires", "Chile": "Santiago"}
Total de alunos: 5
Mapa vazio? false
Dicas Importantes
- Chaves devem implementar
EqeHash: tipos primitivos,Stringe&strjá implementam. Para structs próprias, use#[derive(PartialEq, Eq, Hash)]. - A Entry API evita buscas duplicadas: em vez de verificar com
contains_keye depois inserir, useentry().or_insert()para fazer tudo em uma operação. - A ordem de iteração não é garantida: se precisar de ordem, considere usar
BTreeMap. - Capacidade inicial: use
HashMap::with_capacity(n)quando souber o tamanho aproximado para evitar realocações.
Veja Também
- Variáveis, Tipos e Funções em Rust — fundamentos dos tipos usados como chave e valor
- Rust Cheatsheet — referência rápida incluindo HashMap e outras coleções
- Iterar Coleções em Rust — técnicas avançadas de iteração sobre HashMap e outras coleções
- Filtrar Vetor em Rust — filtragem funcional aplicável também a coleções de pares
- Glossário Rust — termos como Hash, Trait e Derive explicados em português
- Como usar mapas em Go — comparação com a abordagem de mapas em Go