ProgramGuru

Maps, sets and keyed records

Maps, sets and keyed records

A register often needs a mark by student ID rather than by position. A HashMap stores key-value associations, while a HashSet stores unique values. Keys must support equality and hashing so the collection can locate and distinguish them.

What you’ll learn

  • Look up and update marks by student ID.
  • Distinguish unique keys, unique values and report ordering.

Maps, sets and keyed records in action

  1. S01 maps to 80

    The existing mark 80 is found through entry and updated to 85.

    S01 maps to 80
  2. Entry updates it to 85

    S02 has no map entry, so get returns None.

    Entry updates it to 85
  3. Repeated attendance ID counted once

    The set removes duplicate IDs according to equality, leaving two unique attendees.

    Repeated attendance ID counted once
The existing mark 80 is found through entry and updated to 85. S02 has no map entry, so get returns None. The set removes duplicate IDs according to equality, leaving two unique attendees. We print its length rather than an unstable iteration order.

Maps, sets and keyed records explained

Insert associates a key with a value and replaces the previous value for the same key. Get returns an Option containing a reference. The entry API supports creating or updating a value without a separate lookup. Hash collections have no promised iteration order; sort a report explicitly or use an ordered collection such as BTreeMap.

Connect this idea with enums and optional values and result and recoverable errors.

Work through the Rust program

Save the complete source as main.rs in the Rust environment. No standard input is needed.

Rust 2024 · complete program

use std::collections::{HashMap, HashSet};
fn main() {
  let mut marks = HashMap::new();
  marks.insert("S01", 80);
  *marks.entry("S01").or_insert(0) += 5;
  println!("S01: {}", marks["S01"]);
  println!("Missing: {:?}", marks.get("S02"));
  let attendees: HashSet<_> = ["S01", "S01", "S02"].into_iter().collect();
  println!("Unique attendees: {}", attendees.len());
}

Expected output

S01: 85
Missing: None
Unique attendees: 2

Follow the execution

The existing mark 80 is found through entry and updated to 85. S02 has no map entry, so get returns None. The set removes duplicate IDs according to equality, leaving two unique attendees. We print its length rather than an unstable iteration order.

Try the complete program in the Rust compiler. For tests, Cargo commands and local files, use the specified local environment.

Try a small variation

Your task: Does inserting S01 again create a second separate mark under that key?

Rust 2024 · complete program

use std::collections::{HashMap, HashSet};
fn main() {
  let mut marks = HashMap::new();
  marks.insert("S01", 80);
  *marks.entry("S01").or_insert(0) += 5;
  println!("S01: {}", marks["S01"]);
  println!("Missing: {:?}", marks.get("S02"));
  let attendees: HashSet<_> = ["S01", "S01", "S02"].into_iter().collect();
  println!("Unique attendees: {}", attendees.len());
}

Worked answer

No. A map keeps one value per equal key. A new insert replaces that key’s previous value; entry can instead update the existing one.

Mistakes and limits to recognize

Indexing a missing map key panics. The demonstrated S01 indexing is safe only because the program inserted it; use get for uncertain input. Hashing does not sort records and does not itself protect sensitive student data.

Check your understanding

Does inserting S01 again create a second separate mark under that key?
Choose one answer. You can try again.

Answer and explanation

No.

No. A map keeps one value per equal key. A new insert replaces that key’s previous value; entry can instead update the existing one.

Take the idea into your next program

No. A map keeps one value per equal key. A new insert replaces that key’s previous value; entry can instead update the existing one. Indexing a missing map key panics.

Further reading: the official Rust Book on maps, sets and keyed records.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Iterators, closures and transformations →