Rust HashMaps
A HashMap stores data as key-value pairs — you look things up by a key instead of by position, the way you would with an array or vector. If you’ve used a dictionary in Python or an object-as-map in JavaScript, this is the same idea.
Creating a HashMap
Section titled “Creating a HashMap”use std::collections::HashMap;
fn main() { let mut ages = HashMap::new();
ages.insert("Alice", 30); ages.insert("Bob", 25);
println!("{:?}", ages);}use std::collections::HashMap; at the top brings the type into scope — unlike Vec and String, HashMap isn’t available by default, so this line is required.
Looking up a value
Section titled “Looking up a value”use std::collections::HashMap;
fn main() { let mut ages = HashMap::new(); ages.insert("Alice", 30);
match ages.get("Alice") { Some(age) => println!("Alice is {age}"), None => println!("Not found"), }}.get() returns an Option rather than the value directly, because the key might not exist. We’ll cover Option properly on its own page — for now, match with Some/None is the standard way to handle it.
Updating a value
Section titled “Updating a value”Inserting again with the same key overwrites the old value:
use std::collections::HashMap;
fn main() { let mut ages = HashMap::new(); ages.insert("Alice", 30); ages.insert("Alice", 31); // overwrites 30
println!("{:?}", ages.get("Alice"));}If you only want to insert a value when the key doesn’t already exist, use .entry():
use std::collections::HashMap;
fn main() { let mut ages = HashMap::new(); ages.insert("Alice", 30);
ages.entry("Alice").or_insert(99); // Alice exists, so this does nothing ages.entry("Bob").or_insert(25); // Bob doesn't exist, so this inserts it
println!("{:?}", ages);}Looping over a HashMap
Section titled “Looping over a HashMap”use std::collections::HashMap;
fn main() { let mut ages = HashMap::new(); ages.insert("Alice", 30); ages.insert("Bob", 25);
for (name, age) in &ages { println!("{name} is {age}"); }}When to use a HashMap
Section titled “When to use a HashMap”Reach for a HashMap whenever you want to look things up by a name or ID instead of a position — counting word frequency, mapping usernames to user data, caching results by key. If order matters or you’re just working through a plain list, a Vec is the better fit.
Practice
Section titled “Practice”1. A tiny phone book
Section titled “1. A tiny phone book”Store three names and phone numbers in a HashMap. Then look up "Ben" (who is in it) and "Dana" (who isn’t), and print a friendly line for each. Hint: loop over ["Ben", "Dana"] and match on .get(name).
Show solution
use std::collections::HashMap;
fn main() { let mut phone_book = HashMap::new(); phone_book.insert("Ana", "555-1234"); phone_book.insert("Ben", "555-9876"); phone_book.insert("Chen", "555-4321");
for name in ["Ben", "Dana"] { match phone_book.get(name) { Some(number) => println!("{name}: {number}"), None => println!("{name}: not in the phone book"), } }}Output:
Ben: 555-9876Dana: not in the phone bookLooping over the names we want, instead of over the map, also gives us a fixed order. That’s a handy trick whenever you need predictable output from a HashMap.
2. Count the votes
Section titled “2. Count the votes”You have the votes ["red", "blue", "red", "green", "blue", "red"]. Count how many each color got, then print the totals for "red", "green", "blue" and "pink" (which got none). Hint: counts.entry(color).or_insert(0) gives you the current count for that color, starting at 0. Add one to it with *count += 1.
Show solution
use std::collections::HashMap;
fn main() { let votes = ["red", "blue", "red", "green", "blue", "red"]; let mut counts = HashMap::new();
for color in votes { let count = counts.entry(color).or_insert(0); *count += 1; }
for color in ["red", "green", "blue", "pink"] { match counts.get(color) { Some(n) => println!("{color}: {n}"), None => println!("{color}: 0"), } }}Output:
red: 3green: 1blue: 2pink: 0or_insert(0) returns a mutable reference to the value stored in the map, not a copy. The * in *count += 1 means “change the number this points to”, so the map itself gets updated. This “entry, or insert 0, then add 1” pattern is the standard way to count things in Rust.
HashMap<K, V>stores key-value pairs; bring it into scope withuse std::collections::HashMap;..insert(key, value)adds or overwrites;.get(key)looks up and returns anOption..entry(key).or_insert(value)inserts only if the key isn’t already there.- Iteration order isn’t guaranteed — don’t rely on it.
Quick check
Section titled “Quick check”Quick check
1. What do you need to bring HashMap into scope, unlike Vec or String?
2. What does .entry(key).or_insert(value) do?
3. Can you rely on the order entries print when looping over a HashMap?
Score: 0 / 3
Read more
Section titled “Read more”- Storing Keys with Associated Values in Hash Maps — The Rust Book: covers ownership of keys and values, and a word-counting example that updates values.
- HashMap — Rust by Example: a runnable contacts example using
insert,get,removeand loops. HashMap— standard library docs: every method, includingcontains_key,remove,keysandvalues.Entry— standard library docs: everything you can do with.entry(), such asor_insert_withandand_modify.