HashMap

标准的哈希映射,内含针对 HashDoS 攻击的保护措施:

  1. use std::collections::HashMap;
  2. fn main() {
  3. let mut page_counts = HashMap::new();
  4. page_counts.insert("Adventures of Huckleberry Finn", 207);
  5. page_counts.insert("Grimms' Fairy Tales", 751);
  6. page_counts.insert("Pride and Prejudice", 303);
  7. if !page_counts.contains_key("Les Misérables") {
  8. println!(
  9. "We know about {} books, but not Les Misérables.",
  10. page_counts.len()
  11. );
  12. }
  13. for book in ["Pride and Prejudice", "Alice's Adventure in Wonderland"] {
  14. match page_counts.get(book) {
  15. Some(count) => println!("{book}: {count} pages"),
  16. None => println!("{book} is unknown."),
  17. }
  18. }
  19. // Use the .entry() method to insert a value if nothing is found.
  20. for book in ["Pride and Prejudice", "Alice's Adventure in Wonderland"] {
  21. let page_count: &mut i32 = page_counts.entry(book).or_insert(0);
  22. *page_count += 1;
  23. }
  24. println!("{page_counts:#?}");
  25. }

This slide should take about 10 minutes.

  • “HashMap”未在序言中定义,因此需要纳入范围中。

  • 请尝试使用以下代码行。第一行将查看图书是否在 hashmap 中;如果不在,则返回替代值。如果未找到图书,第二行会在 hashmap 中插入替代值。

    1. let pc1 = page_counts
    2. .get("Harry Potter and the Sorcerer's Stone")
    3. .unwrap_or(&336);
    4. let pc2 = page_counts
    5. .entry("The Hunger Games".to_string())
    6. .or_insert(374);
  • 遗憾的是,与“vec!”不同,不存在标准的“hashmap!”宏。

    • 不过,从 Rust 1.56 开始,HashMap 实现了“From<[(K, V); N]>”;+N%5D%3E-for-HashMap%3CK,+V,+RandomState%3E),让我们能够轻松地从字面量数组初始化哈希映射:

      1. let page_counts = HashMap::from([
      2. ("Harry Potter and the Sorcerer's Stone".to_string(), 336),
      3. ("The Hunger Games".to_string(), 374),
      4. ]);
  • 或者,HashMap 也可以基于任何可生成键-值元组的“Iterator”进行构建。

  • 我们要展示“HashMap<String, i32>”,避免将“&str”用作键,以便简化示例。当然,可以在集合中使用引用,但可能会导致借用检查器出现复杂问题。

    • 尝试从上述示例中移除“to_string()”,看看它是否仍可编译。您认为我们可能会在哪些方面遇到问题?
  • 此类型具有几种特定于方法的返回值类型,例如“std::collections::hash_map::Keys”。这些类型通常会出现在 Rust 文档的搜索结果中。向学员展示此类型的文档,以及指向“keys”方法的实用链接。