entry().or_insert()
The map.entry(key).or_insert(default) pattern ensures a key exists in a HashMap<K, V>—inserting default if the key is absent—and returns a mutable reference &mut V to the value in the map so it can be read or modified in place.
Signature and Execution Flow
impl<'a, K, V> Entry<'a, K, V> {
pub fn or_insert(self, default: V) -> &'a mut V
}
let slot: &mut V = map.entry(key).or_insert(default);
│
├── Key already present ──> drops `default`, returns `&mut existing_val`
└── Key absent ──> inserts `(key, default)`, returns `&mut new_val`
Because or_insert returns &'a mut V, dereferencing the return value (*map.entry(k).or_insert(0) += 1) modifies the value directly inside its bucket without a second hash lookup.
Initializing Default Values and Mutating Through &mut V
use std::collections::HashMap;
fn main() {
let mut settings = HashMap::from([("retries", 3_u32)]);
// 1. Key "retries" already exists -> keeps 3, ignores 10:
settings.entry("retries").or_insert(10);
// 2. Key "timeout_sec" does not exist -> inserts 30:
settings.entry("timeout_sec").or_insert(30);
// 3. Mutate the returned `&mut u32` reference directly:
let retries_ref: &mut u32 = settings.entry("retries").or_insert(0);
*retries_ref += 2;
println!(
"retries = {}, timeout_sec = {}",
settings["retries"], settings["timeout_sec"]
);
}
retries = 5, timeout_sec = 30
Using .or_default() When default Is V::default()
Whenever the fallback value passed to .or_insert(...) is 0, false, "", Vec::new(), or Default::default(), prefer .or_default() for brevity (and to avoid evaluating Default::default() when the key is already occupied):
use std::collections::HashMap;
fn main() {
let mut groups: HashMap<&str, Vec<&str>> = HashMap::new();
for (dept, employee) in [("eng", "alice"), ("sales", "bob"), ("eng", "carol")] {
// Inserts an empty `Vec` if `dept` is missing, then pushes `employee`:
groups.entry(dept).or_default().push(employee);
}
println!("eng: {:?}", groups["eng"]);
println!("sales: {:?}", groups["sales"]);
}
eng: ["alice", "carol"]
sales: ["bob"]
Eager Evaluation Caveat of or_insert(default)
Because or_insert(default) is a regular method call, Rust evaluates the argument default before calling or_insert—even when the key is already present in the map! Keep or_insert(val) for cheap stack values (integers, booleans, None, &str), and use .or_insert_with(|| ...) or .or_default() when constructing the fallback value allocates or performs work.