Criando HashMap em Rust: da dor à beleza em 2025
\n\nSe você já programou em Rust e se perguntou "How do I create a HashMap literal?" — você não está sozinho. Essa pergunta no Stack Overflow acumulou milhares de visualizações, e não é à toa. Em linguagens como Python ou JavaScript, criar um dicionário é literalmente um par de chaves. Em Rust, é um pouco mais complicado… mas apenas à primeira vista.
\n\nEm 2025, o ecossistema Rust avançou muito. Surgiram novas macros, o trabalho com constantes melhorou e o compilador ficou ainda mais inteligente. Neste artigo, vamos abordar todas as formas de criar um HashMap, desde as clássicas até as mais modernas. Você aprenderá a escrever código não apenas funcional, mas também bonito e eficiente.
\n\nVamos nessa! 🦀
\n\nPor que o Rust não tem um literal HashMap embutido?
\n\nEsta é, provavelmente, a pergunta mais frequente dos iniciantes. A resposta é simples: Rust não é Python. Rust não tem "mágica" no nível de sintaxe para coleções, porque a linguagem busca previsibilidade e controle sobre a memória.
\n\nImagine que você escreva:
\n\nlet map = {"key1": "value1", "key2": "value2"};\n\nParece lógico? Sim. Mas e se as chaves ou valores não forem strings, mas sim estruturas complexas? Como o compilador saberá qual alocador usar? E quanto ao hashing? Rust deixa essas decisões para o desenvolvedor.
\n\nÉ por isso que, para criar um HashMap na biblioteca padrão, usamos HashMap::new() e os métodos .insert(). Mas, convenhamos, escrever 10 linhas de código para criar um dicionário com três pares é doloroso. Felizmente, existem soluções.
Método nº1: Clássico — HashMap::new() + insert()
\n\nVamos começar pela base. Esta é a forma mais clara e transparente. Você cria um HashMap vazio e o preenche:
\n\nuse std::collections::HashMap;\n\nfn main() {\n let mut scores = HashMap::new();\n scores.insert("Alice".to_string(), 42);\n scores.insert("Bob".to_string(), 27);\n scores.insert("Charlie".to_string(), 35);\n\n println!("{:?}", scores);\n}\n\nVantagens:
\n- \n
- Controle total sobre o processo. \n
- Permite adicionar elementos condicionalmente. \n
- Não requer dependências adicionais. \n
Desvantagens:
\n- \n
- Muito verboso. \n
- Requer
mut. \n - Não é adequado para constantes. \n
Este método é bom para preenchimento dinâmico, mas para dados estáticos é excessivo.
\n\nMétodo nº2: from() — quando os dados já estão prontos
\n\nSe você tem um vetor de tuplas, pode usar HashMap::from():
use std::collections::HashMap;\n\nfn main() {\n let data = vec![\n ("Alice", 42),\n ("Bob", 27),\n ("Charlie", 35),\n ];\n\n let scores: HashMap<&str, i32> = HashMap::from(data);\n println!("{:?}", scores);\n}\n\nIsso já está mais próximo de um "literal". Parece mais limpo, mas ainda requer um vetor intermediário. Funciona rápido, mas para grandes conjuntos de dados pode ser ineficiente devido à dupla alocação de memória.
\n\nMétodo nº3: collect() — abordagem funcional
\n\nOs fãs de iteradores vão gostar deste método:
\n\nuse std::collections::HashMap;\n\nfn main() {\n let scores: HashMap<&str, i32> = [\n ("Alice", 42),\n ("Bob", 27),\n ("Charlie", 35),\n ].iter().cloned().collect();\n\n println!("{:?}", scores);\n}\n\nBonito? Sim. Legível? Mais ou menos. Mas é uma das formas mais idiomáticas em Rust. .iter().cloned().collect() é um padrão padrão para converter um array em uma coleção.
A propósito, se suas chaves e valores implementam Copy, você pode usar .copied() em vez de .cloned() — é um pouco mais rápido.
Método nº4: Macro hashmap! — a salvação de 2025
\n\nAqui está