Reading — step 1 of 5
Learn
HashMap
HashMap<K, V> is Rust's hash table — constant-time key→value storage, the engine behind every counting, grouping, and have-I-seen-it problem. The API differs from other languages in one philosophically Rust way: a missing key is not an error and not a zero — it's an Option, and you say what happens.
The basics
use std::collections::HashMap; // the one import you'll forget
let mut ages: HashMap<String, i32> = HashMap::new();
ages.insert(String::from("alice"), 30);
ages.insert(String::from("bob"), 25);
ages.insert(String::from("bob"), 26); // same key: overwrites, no complaint
ages.remove("alice");
ages.len();
Reading: Option again
match ages.get("bob") {
Some(age) => println!("bob is {age}"),
None => println!("no bob on record"),
}
if let Some(age) = ages.get("bob") { // terser when you only care about Some
println!("{age}");
}
get returns Option<&V> — the presence question and the value arrive together, and the compiler won't let you use the value without acknowledging the None case. Where Go silently hands you a zero and a separate ok flag you might forget to check, Rust bakes the check into the type. Same idea, enforced.
Direct indexing exists (ages["bob"]) and panics on missing keys — same convenient-vs-careful split as Vec.
entry(): the API everyone falls in love with
The counting problem — "increment, but the key might not exist yet" — has a dedicated, beautiful answer:
let mut counts: HashMap<String, i32> = HashMap::new();
for word in words {
*counts.entry(word).or_insert(0) += 1;
}
Read it inside-out: entry(word) is a handle to the slot (existing or vacant); .or_insert(0) fills a vacant slot with 0 and returns a mutable reference either way; *… += 1 increments through that reference. One line, one lookup, no race between "check" and "insert." This is the counting idiom — you will type it in interviews.
Iteration: random on purpose
for (name, age) in &ages {
println!("{name}: {age}");
}
Order is arbitrary and varies run to run (HashDoS resistance, same story as Go). When output must be sorted for a grader: collect and sort first —
let mut keys: Vec<_> = counts.keys().collect();
keys.sort();
Your exercise: Distinct Words
Count distinct words in the input. A set is what you want, and Rust has a real one — HashSet<String> (a HashMap with no values, same use std::collections:: home):
let mut seen = HashSet::new();
for word in words {
seen.insert(word); // duplicates are simply ignored
}
println!("{}", seen.len());
Insert everything, print len() — duplicates cost nothing because sets don't count enthusiasm. If you'd rather practice this lesson's star, tally into a HashMap with the entry idiom instead and print its len(); identical answer, and now you've typed the counting one-liner once before the day an exercise demands the counts themselves.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…