Updating a Value in HashMap in Rust: From Beginner to Pro

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

How to Update a Value in a Mutable HashMap in Rust: From Beginner to Pro

\n\n

Have you ever encountered a situation where you need to update a value in a HashMap in Rust, but the compiler stubbornly rejects your code? If so — you are not alone. The question "How can I update a value in a mutable HashMap?" on Stack Overflow has gathered thousands of views, which means even experienced developers sometimes get confused about the nuances of working with this collection.

\n\n

In this article, we will break down all the ways to update values in a HashMap in Rust: from the basic insert to the advanced entry().and_modify(). You will learn how to correctly modify data, avoid common mistakes, and write idiomatic code. Let's go!

\n\n

Why is updating in a HashMap not just "take and change"?

\n\n

Unlike many languages, Rust forces you to explicitly work with ownership and borrowing. When you want to update a value in a HashMap, you need to solve three tasks:

\n\n
    \n
  • Check if the key exists — is there already such a value?
  • \n
  • Modify the value — if the key exists, update it
  • \n
  • Insert a new one — if the key does not exist, add it
  • \n
\n\n

Sounds simple? Let's look at the code.

\n\n

Method 1: Classic insert (but with a catch)

\n\n

The most straightforward way is to use insert. It overwrites the value if the key exists, or inserts a new pair if the key does not exist.

\n\n
use std::collections::HashMap;\n\nlet mut scores = HashMap::new();\nscores.insert(String::from("Alice"), 10);\nscores.insert(String::from("Bob"), 20);\n\n// Update the value for Alice\nscores.insert(String::from("Alice"), 15);\n\nprintln!("{:?}", scores); // {"Alice": 15, "Bob": 20}
\n\n

Does it work? Yes. But there is a nuance: insert returns Option<V> — the old value, if it existed. This is useful if you want to keep the previous value. But what if you need to update the value based on the old one? For example, increment a counter by 1?

\n\n
// We want to increment Alice's score by 1\nif let Some(score) = scores.get_mut("Alice") {\n    *score += 1;\n}
\n\n

This works, but requires two operations: checking for existence and modifying. And if the key doesn't exist? You would have to do the insertion separately. Not very elegant.

\n\n

Method 2: Entry API — the king of updates

\n\n

Rust has a powerful tool — the Entry API. It allows you to check for the existence of a key, update, or insert a value in a single expression. This is the idiomatic way to work with HashMap.

\n\n
use std::collections::HashMap;\n\nlet mut word_count = HashMap::new();\n\n// Count words in a sentence\nfor word in "hello world hello Rust".split_whitespace() {\n    let count = word_count.entry(word.to_string()).or_insert(0);\n    *count += 1;\n}\n\nprintln!("{:?}", word_count);\n// {"hello": 2, "world": 1, "Rust": 1}
\n\n

Let's break down the magic:

\n
    \n
  • entry(key) — creates an entry for the key
  • \n
  • or_insert(0) — if the key does not exist, inserts the value 0 and returns a mutable reference to it
  • \n
  • *count += 1 — dereferences the reference and increments the value
  • \n
\n\n

Voila! One line — and we solved the problem. But that's not all.

\n\n

Method 3: and_modify — when you only need to update

\n\n

What if you want to update the value only if the key exists, and if not — do nothing? Or insert a different value? For this, there is and_modify and or_insert in a chain.

\n\n
use std::collections::HashMap;\n\nlet mut inventory = HashMap::new();\ninventory.insert("apples".to_string(), 10);\ninventory.insert("bananas".to_string(), 5);\n\n// Increase the number of apples by 1 if they exist\ninventory.entry("apples".to_string())\n    .and_modify(|                

Blogs

Book Recommendations