HashMap

標準雜湊映射,可防範 HashDoS 攻擊:

use std::collections::HashMap;

fn main() {
    let mut page_counts = HashMap::new();
    page_counts.insert("Adventures of Huckleberry Finn".to_string(), 207);
    page_counts.insert("Grimms' Fairy Tales".to_string(), 751);
    page_counts.insert("Pride and Prejudice".to_string(), 303);

    if !page_counts.contains_key("Les Misérables") {
        println!(
            "We know about {} books, but not Les Misérables.",
            page_counts.len()
        );
    }

    for book in ["Pride and Prejudice", "Alice's Adventure in Wonderland"] {
        match page_counts.get(book) {
            Some(count) => println!("{book}: {count} pages"),
            None => println!("{book} is unknown."),
        }
    }

    // Use the .entry() method to insert a value if nothing is found.
    for book in ["Pride and Prejudice", "Alice's Adventure in Wonderland"] {
        let page_count: &mut i32 = page_counts.entry(book.to_string()).or_insert(0);
        *page_count += 1;
    }

    println!("{page_counts:#?}");
}
This slide should take about 10 minutes.
  • 我們一開始並未定義 HashMap,因此現在需要將其納入課程範圍。

  • 請嘗試使用以下幾行程式碼。第一行會查看書籍是否在雜湊表中,如果不在,系統會傳回替代值。如果系統找不到書籍,第二行會在雜湊表中插入替代值。

    let pc1 = page_counts
        .get("Harry Potter and the Sorcerer's Stone")
        .unwrap_or(&336);
    let pc2 = page_counts
        .entry("The Hunger Games".to_string())
        .or_insert(374);
  • 可惜的是,並沒有所謂標準的 hashmap! 巨集。這點與 vec! 不同。

    • 不過,自 Rust 1.56 起,HashMap 會實作 From<[(K, V); N]>,以便讓我們能從常值陣列初始化雜湊映射:

      let page_counts = HashMap::from([
        ("Harry Potter and the Sorcerer's Stone".to_string(), 336),
        ("The Hunger Games".to_string(), 374),
      ]);
  • 或者,您也可以透過任何能產生鍵/值元組的 Iterator 建立 HashMap。

  • 我們示範的是 HashMap<String, i32>,請避免使用 `&str 做為鍵,讓範例變得更簡單。當然,也可以在集合中使用參照,但這可能會使借用檢查器變得複雜。

    • 請嘗試從上述範例中移除 to_string(),看看是否仍可編譯。您認為我們可能會在哪裡遇到問題?
  • 這個型別有多個「方法專屬」的傳回型別,例如 std::collections::hash_map::Keys。這些型別經常會在 Rust 文件的搜尋結果中出現。請向學生展示這個型別的文件,以及可返回 keys 方法的實用連結。