DEV Community

Subesh Yadav
Subesh Yadav

Posted on • Edited on

🚀 Day 14 of #100DaysOfRust: Deep Dive into HashMaps + Intro to Error Handling

Welcome to Day 14! Today, I explored the final primary collection in Rust—Hash Maps—along with a sneak peek into Rust’s approach to error handling. Let’s walk through everything I learned.

🗃️ HashMaps: Key-Value Storage

Rust’s HashMap lets you store data as key-value pairs using a hashing function. It’s great when you need lookup access via keys instead of indices.

Other names in different languages: dictionary, object, map, associative array.

✅ Creating a HashMap

use std::collections::HashMap;

let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
Enter fullscreen mode Exit fullscreen mode
  • We import HashMap from std::collections.
  • Insert elements using insert(key, value).
  • All keys must be of the same type, and all values must be of the same type.

🔍 Accessing Values

let team_name = String::from("Blue");
let score = scores.get(&team_name).copied().unwrap_or(0);
get returns an Option<&V>.
Enter fullscreen mode Exit fullscreen mode

Use .copied().unwrap_or(0) to convert to actual value or provide a fallback.

🔁 Iterating Over a HashMap

for (key, value) in &scores {
    println!("{key}: {value}");
}
Enter fullscreen mode Exit fullscreen mode
  • Iterates in arbitrary order.
  • Keys and values are destructured in the loop.

🛠️ Ownership Rules in HashMaps

let key = String::from("Color");
let value = String::from("Blue");

let mut map = HashMap::new();
map.insert(key, value);
// key and value are now moved!
Enter fullscreen mode Exit fullscreen mode
  • If types like String (non-Copy) are inserted, they are moved.
  • If references are inserted, ensure they outlive the HashMap.

🔁 Updating a HashMap

Rust offers multiple update strategies:

🔄 Overwrite Existing Value

scores.insert(String::from("Blue"), 25);
Enter fullscreen mode Exit fullscreen mode
  • Overwrites previous value.

✨ Insert If Absent – entry().or_insert()

scores.entry(String::from("Yellow")).or_insert(50);
scores.entry(String::from("Blue")).or_insert(50);
Enter fullscreen mode Exit fullscreen mode
  • If the key exists, it does nothing.
  • If the key is missing, inserts the value.

Result:

{"Yellow": 50, "Blue": 10}
Enter fullscreen mode Exit fullscreen mode

📊 Count Word Occurrences

let text = "hello world wonderful world";

let mut map = HashMap::new();
for word in text.split_whitespace() {
    let count = map.entry(word).or_insert(0);
    *count += 1;
}

println!("{map:?}");
Enter fullscreen mode Exit fullscreen mode

Result:

{"world": 2, "hello": 1, "wonderful": 1}
Enter fullscreen mode Exit fullscreen mode
  • entry provides a mutable reference.
  • You must dereference (*count) to update.

🔐 Hashing and Security

  • Rust uses SipHash by default to defend against DoS attacks.
  • If performance is critical, switch to a custom hasher (implementing BuildHasher).

🧨 Sneak Peek into Error Handling

Rust separates recoverable and unrecoverable errors.

❌ Unrecoverable Errors — panic!

Used when the program hits a bug and cannot continue.

panic!("Something went wrong!");
Enter fullscreen mode Exit fullscreen mode

✔️ Recoverable Errors — Result

Used when errors can be handled gracefully (e.g., missing file).

fn read_file(path: &str) -> Result<String, std::io::Error> {
    std::fs::read_to_string(path)
}
Enter fullscreen mode Exit fullscreen mode

Rust forces you to deal with errors explicitly—either handle or propagate them. This leads to more robust and predictable code.

📌 Summary

✔️ Things we have covered here:

  • Creating and using HashMap
  • Ownership rules
  • Accessing and iterating
  • Updating with insert, entry().or_insert()
  • Word frequency counting
  • Hashing and performance
  • Quick intro to error handling with panic! and Result

Tomorrow, we’ll dive deeper into error handling!

Stay tuned for Day 15 tomorrow! 🦀
Happy Rusting!

Top comments (0)