Hash Maps and Hash Sets

get() and get_mut()

HashMap<K, V> provides .get(&q), .get_key_value(&q), .get_mut(&q), and .get_disjoint_mut([&q1, &q2]) for safe, non-panicking key lookups in $O(1)$ average time, alongside the panicking index operator map[&q].

Signatures and the Borrow<Q> Parameter

impl<K: Eq + Hash, V, S: BuildHasher> HashMap<K, V, S> {
    pub fn get<Q>(&self, k: &Q) -> Option<&V>
    where
        K: Borrow<Q>,
        Q: Hash + Eq + ?Sized;

    pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
    where
        K: Borrow<Q>,
        Q: Hash + Eq + ?Sized;

    pub fn get_mut<Q>(&self, k: &Q) -> Option<&mut V>
    where
        K: Borrow<Q>,
        Q: Hash + Eq + ?Sized;
}

Because get and get_mut accept any &Q where K: Borrow<Q> and Q: Hash + Eq + ?Sized, you can query a HashMap<String, V> using a &str literal or slice without allocating a temporary String!

Lookup Expression Return Type Missing Key Behavior
map.get(&q) Option<&V> Returns None
map.get_key_value(&q) Option<(&K, &V)> Returns None
map.get_mut(&q) Option<&mut V> Returns None
map[&q] &V (shared only; IndexMut is not implemented!) Panics at runtime

(Note: Unlike Vec<T>, HashMap<K, V> does not implement IndexMut (map[&k] = v does not exist), because map[&k] cannot know whether you intend to insert a new key or panic on a missing key; use map.insert(k, v) or *map.get_mut(&k).unwrap() = v instead.)

Querying and Mutating Values with get() and get_mut()

use std::collections::HashMap;

fn main() {
    let mut balances = HashMap::from([
        (String::from("alice"), 500_i64),
        (String::from("bob"), 250),
    ]);

    // 1. Lookup on `HashMap<String, i64>` using a `&str` slice (via `String: Borrow<str>`):
    let alice_bal: Option<i64> = balances.get("alice").copied();
    let unknown_bal: Option<i64> = balances.get("charlie").copied();
    println!("Alice: {alice_bal:?}, Charlie: {unknown_bal:?}");

    // 2. Mutate an existing value in place with `get_mut`:
    if let Some(bal) = balances.get_mut("bob") {
        *bal += 100;
    }
    println!("Bob after deposit: {}", balances["bob"]);
}
Alice: Some(500), Charlie: None
Bob after deposit: 350

Mutating Multiple Keys Simultaneously with get_disjoint_mut

Just like Vec::get_disjoint_mut, map.get_disjoint_mut([&k1, &k2]) returns [Option<&mut V>; N] (or panics if k1 == k2), allowing you to mutate two distinct keys in the same HashMap at the same time:

use std::collections::HashMap;

fn main() {
    let mut accounts = HashMap::from([("alice", 1_000_i64), ("bob", 400)]);

    if let [Some(from), Some(to)] = accounts.get_disjoint_mut(["alice", "bob"]) {
        *from -= 250;
        *to += 250;
    }

    println!("alice={}, bob={}", accounts["alice"], accounts["bob"]);
}
alice=750, bob=650