Creación de HashMap en Rust: del dolor a la belleza en 2025
\n\nSi alguna vez has escrito en Rust y te has preguntado "How do I create a HashMap literal?" — no estás solo. Esta pregunta en Stack Overflow ha acumulado miles de visitas, y con razón. En lenguajes como Python o JavaScript, crear un diccionario es literalmente un par de llaves. En Rust, todo es un poco más complicado… pero solo a primera vista.
\n\nEn 2025, el ecosistema de Rust ha avanzado mucho. Han aparecido nuevas macros, ha mejorado el trabajo con constantes y el compilador se ha vuelto aún más inteligente. En este artículo, analizaremos todas las formas de crear un HashMap, desde las clásicas hasta las más modernas. Aprenderás a escribir código no solo funcional, sino también elegante y eficiente.
\n\n¡Allá vamos! 🦀
\n\n¿Por qué Rust no tiene un literal HashMap incorporado?
\n\nEsta es, probablemente, la pregunta más frecuente de los principiantes. La respuesta es simple: Rust no es Python. Rust no tiene "magia" a nivel de sintaxis para las colecciones porque el lenguaje busca previsibilidad y control sobre la memoria.
\n\nImagina que escribes:
\n\nlet map = {"key1": "value1", "key2": "value2"};\n\n¿Parece lógico? Sí. Pero, ¿y si las claves o los valores no son cadenas, sino estructuras complejas? ¿Cómo sabría el compilador qué asignador usar? ¿Y qué pasa con el hash? Rust deja estas decisiones al desarrollador.
\n\nPor eso, para crear un HashMap en la biblioteca estándar se usa HashMap::new() y los métodos .insert(). Pero, admitámoslo, escribir 10 líneas de código para crear un diccionario de tres pares es un dolor. Afortunadamente, hay soluciones.
Método n.º 1: Clásico — HashMap::new() + insert()
\n\nEmpecemos por lo básico. Esta es la forma más clara y transparente. Creas un HashMap vacío y lo llenas:
\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\nVentajas:
\n- \n
- Control total sobre el proceso. \n
- Se pueden añadir elementos condicionalmente. \n
- No requiere dependencias adicionales. \n
Desventajas:
\n- \n
- Verboso. \n
- Requiere
mut. \n - No es adecuado para constantes. \n
Este método es bueno para el llenado dinámico, pero para datos estáticos es excesivo.
\n\nMétodo n.º 2: from() — cuando los datos ya están listos
\n\nSi tienes un vector de tuplas, puedes 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\nEsto ya se acerca más a un "literal". Se ve más limpio, pero aún requiere un vector intermedio. Funciona rápido, pero para conjuntos de datos grandes puede ser ineficiente debido a la doble asignación de memoria.
\n\nMétodo n.º 3: collect() — enfoque funcional
\n\nA los fanáticos de los iteradores les gustará este 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\n¿Bonito? Sí. ¿Legible? Con reservas. Pero es una de las formas más idiomáticas en Rust. .iter().cloned().collect() es un patrón estándar para convertir un array en una colección.
Por cierto, si tus claves y valores implementan Copy, puedes usar .copied() en lugar de .cloned() — es un poco más rápido.
Método n.º 4: Macro hashmap! — el salvavidas de 2025
\n\nAquí está