Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Rust Dictionary

  1. Home
  2. Rust Dictionary
  3. HashMap::contains_key() / remove() / entry()

HashMap::contains_key() / remove() / entry()

Since: Rust 1.0(2015)

Rust's HashMap provides contains_key() to check for key existence, remove() to delete entries, and the entry().or_insert() API to insert a value only when the key is absent.

Syntax

use std::collections::HashMap;

// Check whether a key exists (returns bool).
let exists = map.contains_key("Black Flash");

// Remove a key and its value (returns Option<V>).
let removed = map.remove("Black Flash"); // Some(value) or None

// entry API: insert if the key is absent.
map.entry("key".to_string()).or_insert(0);

// entry API: update an existing value.
let count = map.entry("key".to_string()).or_insert(0);
*count += 1; // Increment the value.

Method Reference

MethodDescription
map.contains_key(&key)Returns true if the key exists.
map.remove(&key)Removes the key and returns Some(value) if it existed, or None.
map.remove_entry(&key)Removes and returns the key-value pair as a tuple.
map.entry(key)Returns an Entry for the key (OccupiedEntry or VacantEntry).
.or_insert(value)Inserts the value if the entry is vacant, then returns a mutable reference.
.or_insert_with(|| ...)Inserts the closure's return value if the entry is vacant.
.or_default()Inserts the default value (Default::default()) if the entry is vacant.
.and_modify(|v| ...)Modifies the value only if the entry is occupied.
map.retain(|k, v| ...)Retains only entries that satisfy the predicate.

Sample Code

sample_hashmap_contains_key_remove.rs
use std::collections::HashMap;

fn main() {
    let mut map: HashMap<String, i32> = HashMap::new();
    map.insert("Black Flash".to_string(), 3);
    map.insert("Domain Expansion".to_string(), 5);
    map.insert("Reverse Cursed Technique".to_string(), 2);

    // Check for key existence with contains_key().
    println!("Black Flash exists?: {}", map.contains_key("Black Flash")); // true
    println!("Cursed Energy exists?: {}", map.contains_key("Cursed Energy")); // false

    // Delete an entry with remove().
    let removed = map.remove("Domain Expansion");
    println!("removed value: {:?}", removed); // Some(5)
    println!("length after removal: {}", map.len()); // 2

    let none = map.remove("Cursed Energy"); // Key does not exist
    println!("remove non-existent key: {:?}", none); // None

    // --- entry API ---
    // Count technique usage (a classic entry API use case).
    let cursed_techniques = "domain_expansion reverse_technique domain_expansion black_flash reverse_technique black_flash black_flash";
    let mut counts: HashMap<String, i32> = HashMap::new();

    for technique in cursed_techniques.split_whitespace() {
        let count = counts.entry(technique.to_string()).or_insert(0);
        *count += 1; // Increment through the mutable reference.
    }
    println!("technique counts: {:?}", counts);

    // Use or_default() for the Default trait's default value.
    let mut vmap: HashMap<String, Vec<i32>> = HashMap::new();
    vmap.entry("evens".to_string()).or_default().push(2);
    vmap.entry("evens".to_string()).or_default().push(4);
    vmap.entry("odds".to_string()).or_default().push(1);
    println!("groups: {:?}", vmap);

    // and_modify() changes only existing values.
    let mut scores: HashMap<String, i32> = HashMap::new();
    scores.insert("Gojo Satoru".to_string(), 90);
    scores.entry("Gojo Satoru".to_string()).and_modify(|s| *s += 10);
    scores.entry("Ryomen Sukuna".to_string()).and_modify(|s| *s += 10).or_insert(0);
    println!("scores: {:?}", scores); // Gojo Satoru: 100, Ryomen Sukuna: 0

    // retain() keeps only entries that satisfy the condition.
    let mut m: HashMap<&str, i32> = [("a", 1), ("b", 2), ("c", 3), ("d", 4)]
        .iter().cloned().collect();
    m.retain(|_, v| *v >= 3); // Keep only entries where value >= 3.
    println!("retain(value >= 3): {:?}", m);
}

Compile with the following command:

rustc hashmap_contains_key_remove.rs
./hashmap_contains_key_remove
Black Flash exists?: true
Cursed Energy exists?: false
removed value: Some(5)
length after removal: 2
remove non-existent key: None
technique counts: {"domain_expansion": 2, "reverse_technique": 2, "black_flash": 3}
groups: {"evens": [2, 4], "odds": [1]}
scores: {"Gojo Satoru": 100, "Ryomen Sukuna": 0}
retain(value >= 3): {"c": 3, "d": 4}

Common Mistakes

Common mistake 1: borrow error when using entry() and reading the map simultaneously

Calling entry() takes a mutable borrow of the map. Trying to read the map while holding the returned mutable reference is a compile error.

use std::collections::HashMap;

fn main() {
    let mut scores: HashMap<String, i32> = HashMap::new();
    scores.insert("Gojo Satoru".to_string(), 90);

    // Compile error: cannot borrow `scores` as immutable while a mutable borrow is active
    // let e = scores.entry("Gojo Satoru".to_string()).or_insert(0);
    // println!("{}", scores.get("Gojo Satoru").unwrap()); // NG
    // *e += 1;
}

The same logic can also be written as:

use std::collections::HashMap;

fn main() {
    let mut scores: HashMap<String, i32> = HashMap::new();
    scores.insert("Gojo Satoru".to_string(), 90);

    // Correct: finish using the mutable reference before reading the map
    {
        let e = scores.entry("Gojo Satoru".to_string()).or_insert(0);
        *e += 10;
    }
    println!("{}", scores["Gojo Satoru"]); // 100
}

Common mistake 2: searching twice with contains_key() then get()

Calling contains_key() followed by get() performs two lookups for the same key. Using get() directly and handling the Option is more efficient.

use std::collections::HashMap;

fn main() {
    let mut map: HashMap<String, i32> = HashMap::new();
    map.insert("Fushiguro Megumi".to_string(), 80);

    // Inefficient: two lookups for the same key
    if map.contains_key("Fushiguro Megumi") {
        let val = map.get("Fushiguro Megumi").unwrap();
        println!("value: {}", val);
    }
}

The same logic can also be written as:

use std::collections::HashMap;

fn main() {
    let mut map: HashMap<String, i32> = HashMap::new();
    map.insert("Fushiguro Megumi".to_string(), 80);

    // Efficient: one lookup, handle the Option directly
    if let Some(val) = map.get("Fushiguro Megumi") {
        println!("value: {}", val);
    }
}

Overview

The entry API is one of the most idiomatic ways to use a HashMap. It lets you safely and efficiently express "insert if absent, update if present." It is commonly used for aggregation tasks like counting occurrences.

or_insert() returns a mutable reference (&mut V) to the value. Through this reference you can mutate the value, enabling operations like incrementing or appending to a vector.

HashMap has no built-in contains_value() method. To find a key that holds a specific value, use values().any(|v| v == &target) or iter().find(|(k, v)| v == &&target).

For creating and querying a HashMap, see HashMap::new() / insert() / get(). For iteration, see HashMap::keys() / values() / iter().

If you find any errors or copyright issues, please .