Créer un HashMap en Rust : de la douleur à la beauté en 2025
\n\nSi vous avez déjà programmé en Rust et vous êtes demandé "How do I create a HashMap literal?" — vous n'êtes pas seul. Cette question sur Stack Overflow a recueilli des milliers de vues, et pour cause. Dans des langages comme Python ou JavaScript, créer un dictionnaire se résume à quelques accolades. En Rust, c'est un peu plus complexe… mais seulement à première vue.
\n\nEn 2025, l'écosystème Rust a fait un bond en avant. De nouvelles macros sont apparues, le travail avec les constantes s'est amélioré, et le compilateur est devenu encore plus intelligent. Dans cet article, nous allons passer en revue toutes les méthodes de création d'un HashMap, des plus classiques aux plus modernes. Vous apprendrez à écrire non seulement un code fonctionnel, mais aussi un code élégant et efficace.
\n\nC'est parti ! 🦀
\n\nPourquoi Rust n'a-t-il pas de littéral HashMap intégré ?
\n\nC'est sans doute la question la plus fréquente des débutants. La réponse est simple : Rust n'est pas Python. Rust n'a pas de "magie" syntaxique pour les collections, car le langage vise la prévisibilité et le contrôle de la mémoire.
\n\nImaginez que vous écrivez :
\n\nlet map = {"key1": "value1", "key2": "value2"};\n\nCela semble logique ? Oui. Mais que faire si les clés ou les valeurs ne sont pas des chaînes, mais des structures complexes ? Comment le compilateur saurait-il quel allocateur utiliser ? Et le hachage ? Rust laisse ces décisions au développeur.
\n\nC'est pourquoi, pour créer un HashMap dans la bibliothèque standard, on utilise HashMap::new() et les méthodes .insert(). Mais, avouons-le, écrire 10 lignes de code pour créer un dictionnaire de trois paires, c'est pénible. Heureusement, il existe des solutions.
Méthode n°1 : La classique — HashMap::new() + insert()
\n\nCommençons par les bases. C'est la méthode la plus compréhensible et transparente. Vous créez un HashMap vide et vous le remplissez :
\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\nAvantages :
\n- \n
- Contrôle total du processus. \n
- Possibilité d'ajouter des éléments conditionnellement. \n
- Aucune dépendance supplémentaire requise. \n
Inconvénients :
\n- \n <>Verbeux.\n
- Nécessite
mut. \n - Ne convient pas aux constantes. \n
Cette méthode est bonne pour un remplissage dynamique, mais pour des données statiques, elle est excessive.
\n\nMéthode n°2 : from() — quand les données sont déjà prêtes
\n\nSi vous avez un vecteur de tuples, vous pouvez utiliser 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\nC'est déjà plus proche d'un "littéral". Cela semble plus propre, mais nécessite toujours un vecteur intermédiaire. C'est rapide, mais pour de grands ensembles de données, cela peut être inefficace en raison d'une double allocation mémoire.
\n\nMéthode n°3 : collect() — l'approche fonctionnelle
\n\nLes fans d'itérateurs apprécieront cette méthode :
\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\nBeau ? Oui. Lisible ? À la limite. Mais c'est l'une des méthodes les plus idiomatiques en Rust. .iter().cloned().collect() est un motif standard pour convertir un tableau en collection.
D'ailleurs, si vos clés et valeurs implémentent Copy, vous pouvez utiliser .copied() au lieu de .cloned() — c'est un peu plus rapide.
Méthode n°4 : La macro hashmap! — le salut de 2025
\n\nEt voici