Files
2026-03-11 09:12:14 +08:00
..
2026-03-11 09:12:14 +08:00

好主意。HashMapHashSet 是 Rust 最核心的标准库容器之一,而且很多 Rust 代码都会围绕它们写。如果你打算系统试一遍,我建议按 结构 → 常用方法 → 进阶 API → 迭代器 → 实用技巧 这样理解,会非常清晰。

它们都在:

use std::collections::{HashMap, HashSet};

本质上:

  • HashMap<K, V>:键值对
  • HashSet<T>:只有键(本质上是 HashMap<T, ()>

一、HashMap 结构

HashMap<K, V>

要求:

K: Eq + Hash

因为要进行哈希比较。

例子:

use std::collections::HashMap;

let mut map: HashMap<String, i32> = HashMap::new();

二、HashMap 创建方法

1 new

let map: HashMap<i32, i32> = HashMap::new();

2 with_capacity

提前分配空间。

let map: HashMap<i32, i32> = HashMap::with_capacity(100);

减少 rehash。


3 from

let map = HashMap::from([
    ("a", 1),
    ("b", 2),
]);

三、HashMap 基本操作

1 插入 insert

map.insert("apple", 3);

返回:

Option<V>

如果 key 已存在:

let old = map.insert("apple", 5);

old = Some(3)


2 获取 get

map.get("apple")

返回:

Option<&V>

例子:

if let Some(v) = map.get("apple") {
    println!("{}", v);
}

3 获取可变值 get_mut

map.get_mut("apple")

返回:

Option<&mut V>

例子:

if let Some(v) = map.get_mut("apple") {
    *v += 1;
}

4 删除 remove

map.remove("apple")

返回:

Option<V>

5 是否包含 key

map.contains_key("apple")

返回:

bool

四、Entry APIRust最强HashMap接口

Rust 的 HashMap 最强 API 是 entry()

它避免:

  • 先查
  • 再插入

这种两次查找。


1 entry

map.entry("apple")

返回:

Entry<K,V>

有两种:

Occupied
Vacant

2 or_insert

map.entry("apple").or_insert(0);

含义:

如果没有 -> 插入0
如果有 -> 返回已有值

返回:

&mut V

例子:

*map.entry("apple").or_insert(0) += 1;

经典 词频统计

for word in words {
    *map.entry(word).or_insert(0) += 1;
}

3 or_insert_with

延迟计算。

map.entry("key").or_insert_with(|| expensive());

只有需要时才计算。


4 and_modify

map.entry("apple")
   .and_modify(|v| *v += 1)
   .or_insert(1);

意思:

如果存在 -> 修改
如果不存在 -> 插入

非常常用。


五、HashMap 遍历

1 遍历 key value

for (k, v) in &map {
    println!("{} {}", k, v);
}

类型:

(&K, &V)

2 只遍历 key

for k in map.keys() {
}

3 只遍历 value

for v in map.values() {
}

4 可变 value

for v in map.values_mut() {
    *v += 1;
}

六、HashMap 容量操作

len

map.len()

is_empty

map.is_empty()

clear

map.clear()

删除全部。


capacity

map.capacity()

reserve

map.reserve(100);

增加容量。


shrink_to_fit

map.shrink_to_fit();

释放多余空间。


七、HashMap 进阶 API

remove_entry

删除并返回 key value

map.remove_entry("apple")

返回:

Option<(K,V)>

retain

过滤元素

map.retain(|k, v| *v > 10);

drain

清空并返回迭代器

for (k, v) in map.drain() {
}

八、HashSet

HashSet 本质:

HashMap<T, ()>

所以 API 很类似。


九、HashSet 创建

use std::collections::HashSet;

let mut set = HashSet::new();

from

let set = HashSet::from([1,2,3]);

with_capacity

HashSet::with_capacity(100);

十、HashSet 基本操作

insert

set.insert(10);

返回:

bool

是否新插入。


contains

set.contains(&10);

remove

set.remove(&10);

len

set.len()

clear

set.clear()

十一、HashSet 集合运算(非常强)

union

并集

set1.union(&set2)

intersection

交集

set1.intersection(&set2)

difference

差集

set1.difference(&set2)

symmetric_difference

对称差

set1.symmetric_difference(&set2)

例子:

for x in set1.intersection(&set2) {
    println!("{}", x);
}

十二、HashSet 遍历

for v in &set {
    println!("{}", v);
}

十三、HashSet 关系判断

is_subset

set1.is_subset(&set2)

is_superset

set1.is_superset(&set2)

is_disjoint

set1.is_disjoint(&set2)

两个集合是否没有交集。


十四、一个典型例子

去重

let nums = vec![1,2,2,3,4];

let set: HashSet<_> = nums.into_iter().collect();

统计词频

let mut map = HashMap::new();

for word in text.split_whitespace() {
    *map.entry(word).or_insert(0) += 1;
}

十五、Rust HashMap 一个隐藏知识

Rust标准库 HashMap 不是自己实现的

它使用:

SwissTable

来自:

Google

算法实现来自:

Abseil

特点:

  • SIMD 查找
  • robin hood hashing
  • 非常快