Start learning free

LESSON 110 OF 414 · DICTIONARIES

Dictionaries in Rust: Creating a HashMap

Lesson Read the full explanation

In Rust, a HashMap works like a dictionary — it stores key-value pairs where each key maps to a value. Bring it into scope with use std::collections::HashMap;.

use std::collections::HashMap;

let mut scores: HashMap<&str, i32> = HashMap::new();
scores.insert("Alice", 95);
scores.insert("Bob", 87);
scores.insert("Charlie", 72);

The type parameters <&str, i32> specify the key type and value type. You can also initialize using HashMap::from:

use std::collections::HashMap;

let ages: HashMap<&str, i32> = HashMap::from([
    ("Alice", 25),
    ("Bob", 30),
]);
println!("{}", ages["Alice"]);  // 25
println!("{}", ages.len());     // 2

Assignment
Follow the Coding Tutorial and create a HashMap named scores with three student scores!


Hint
Declare let mut scores: HashMap<&str, i32> = HashMap::new(); then use scores.insert("Alice", 95) to add entries.

STEP 1 OF 2
    Ctrl + Enter to check

    RUST · DICTIONARIES

    Dictionaries in Rust, explained

    What a HashMap is

    A dictionary stores key-value pairs: you look up a value by its key rather than by a position. Rust's dictionary type is HashMap. Typical uses are scores by student name, counts by word, or prices by product code, anywhere you'd otherwise search a list for a matching entry.

    HashMap is not in the prelude, so it has to be imported before it can be used:

    use std::collections::HashMap;

    Without that line, HashMap::new() fails with failed to resolve: use of undeclared type `HashMap`, and the compiler's help suggests the import. The exercise below already has it in place.

    Creating a map

    Start with an empty map and add entries with insert(key, value). The key comes first and the value second:

    use std::collections::HashMap;
    
    let mut scores: HashMap<&str, i32> = HashMap::new();
    scores.insert("Alice", 95);
    scores.insert("Bob", 87);
    scores.insert("Charlie", 72);

    The type HashMap<&str, i32> says that keys are string slices and values are 32-bit integers. You can also leave the annotation out. The compiler infers both types from the first insert call, so let mut scores = HashMap::new(); is enough.

    When you already know the entries, build the map in one expression from an array of pairs:

    let ages: HashMap<&str, i32> = HashMap::from([
        ("Alice", 25),
        ("Bob", 30),
    ]);
    println!("{} {}", ages["Alice"], ages.len());
    25 2

    The method len() returns the number of entries, just as it does for a vector.

    Rules and gotchas

    The map must be mut to change it

    Both insert and remove change the map, so the binding needs let mut. Without it, the compiler says it cannot borrow the map as mutable. A map built once with HashMap::from and never changed can be an ordinary let.

    One type for keys, one for values

    All keys share one type and all values share another. Mixing them, for example inserting a decimal number into a map of integers, is a "mismatched types" compile error.

    Keys are unique

    Inserting a key that is already there replaces its value and returns the old one wrapped in Some. A brand-new key returns None.

    let mut m: HashMap<String, i32> = HashMap::new();
    println!("{:?}", m.insert("a".to_string(), 1));
    println!("{:?}", m.insert("a".to_string(), 2));
    println!("{:?}", m);
    None
    Some(1)
    {"a": 2}

    Checking and removing

    The method contains_key tells you whether a key is present, and remove deletes an entry and returns its old value as an Option. With the three scores above, scores.contains_key("Bob") is true, and scores.remove("Bob") returns Some(87) and leaves two entries.

    No guaranteed order

    A HashMap doesn't remember insertion order, and the order in which it lists its entries can differ from one run to the next. Don't rely on it. If you need sorted output, collect the entries into a vector and sort that.

    The lesson's exercise

    The task is to create a map named scores with three students.

    1. Create an empty map. Declare scores with let mut and HashMap::new(). It must be mut because the next step adds entries. No type annotation is needed, since the inserts that follow tell the compiler the key and value types.
    2. Insert three entries. One insert call per student: "Alice" with 95, "Bob" with 87 and "Charlie" with 72.
            let mut scores = HashMap::new();
            scores.insert("Alice", 95);
            scores.insert("Bob", 87);
            scores.insert("Charlie", 72);

    Afterwards scores.len() is 3.

    Key takeaways

    • A HashMap<K, V> maps keys of type K to values of type V; import it with use std::collections::HashMap;.
    • Create it with HashMap::new() and insert(key, value), or in one step with HashMap::from([...]).
    • Declare it mut if you will add or remove entries.
    • Inserting an existing key replaces the value; the iteration order is not defined.
    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free