Hash Maps and Hash Sets
Inserting and Updating Values
HashMap<K, V> provides several ways to insert new key-value pairs and update existing values, depending on whether you want to overwrite unconditionally (.insert()), keep the existing value (.entry(k).or_insert()), or transform the existing value in place.
Behavior of map.insert(k, v)
pub fn insert(&mut self, k: K, v: V) -> Option<V>
- If
kis not in the map: Inserts(k, v)and returnsNone. - If an equal key
k_old == kis already in the map:- Replaces the value with
vand returnsSome(old_value). - Does NOT update the existing key
k_oldin the table! This nuance matters for types wherek1 == k2does not meank1andk2are identical (such as case-insensitive string wrappers or structs comparing only by ID).
- Replaces the value with
use std::collections::HashMap;
fn main() {
let mut timeouts = HashMap::new();
// 1. First insertion of "db" returns `None`:
let prev1 = timeouts.insert("db", 3_000_u64);
println!("1st insert of 'db' returned: {prev1:?}");
// 2. Second insertion of "db" overwrites 3000 with 5000 and returns `Some(3000)`:
let prev2 = timeouts.insert("db", 5_000);
println!("2nd insert of 'db' returned: {prev2:?}");
println!("Current 'db' timeout: {}", timeouts["db"]);
}
1st insert of 'db' returned: None
2nd insert of 'db' returned: Some(3000)
Current 'db' timeout: 5000
Ownership of Keys and Values Passed to insert()
Calling map.insert(k, v) moves both k and v into the HashMap. If k or v is a non-Copy type like String, the original variables cannot be used after insert unless cloned:
use std::collections::HashMap;
fn main() {
let key = String::from("region");
let val = String::from("ap-south-1");
let mut config = HashMap::new();
config.insert(key, val); // Moves `key` and `val` into `config`
println!("Stored region: {}", config["region"]);
}
Stored region: ap-south-1
Comparing the Four Update Patterns on HashMap<K, V>
| Update Goal | Idiomatic Expression | Key Lookup Count |
|---|---|---|
| Overwrite unconditionally (or insert if missing) | map.insert(k, new_val) |
1 |
| Insert only if missing (keep existing value) | map.entry(k).or_insert(default_val) |
1 |
| Modify only if already present (do nothing if missing) | if let Some(v) = map.get_mut(&k) { *v += 1; } |
1 |
| Modify if present, or insert default if missing | *map.entry(k).or_insert(0) += 1; or map.entry(k).and_modify(f).or_insert(init) |
1 |
| Merge another map/iterator (overwriting matching keys) | map.extend(other_map) |
1 per item |
use std::collections::HashMap;
fn main() {
let mut stock = HashMap::from([("ssd", 10_u32), ("ram", 25)]);
// 1. Update only if already present:
if let Some(qty) = stock.get_mut("ssd") {
*qty += 5;
}
// 2. Bulk insert/overwrite from an array or iterator via `extend`:
stock.extend([("gpu", 4), ("ram", 30)]);
println!("ssd={}, ram={}, gpu={}", stock["ssd"], stock["ram"], stock["gpu"]);
}
ssd=15, ram=30, gpu=4