Rust专项——集合与迭代器基础:Vec、HashMap、HashSet 详解
·
本章系统讲解 Rust 标准库中的集合(Collections)与迭代器(Iterator)。集合是存储多个值的容器;迭代器提供统一、零成本的遍历方式,是 Rust 函数式编程与高性能代码的核心。
1. Vec:动态数组详解
1.1 创建与初始化
let mut v1: Vec<i32> = Vec::new(); // 空向量
let v2 = vec![1, 2, 3]; // 宏初始化
let v3 = Vec::with_capacity(10); // 预分配容量
// 填充方式
v1.push(10);
v1.extend_from_slice(&[20, 30]);
v1.insert(1, 15); // 在索引1插入15
1.2 访问与修改
fn main() {
// 修正:将 v 声明为可变向量(添加 mut 关键字)
let mut v = vec![1, 2, 3, 4, 5];
// 安全访问(不可变,无需 mut)
if let Some(val) = v.get(2) { // 返回 Option<&T>
println!("索引2的值: {}", val);
}
// 直接索引(越界会panic)
let third = v[2]; // 3
println!("直接索引获取的值: {}", third);
// 可变借用(需要 v 是可变的)
if let Some(val) = v.get_mut(2) {
*val = 99;
println!("修改后索引2的值: {}", val);
}
// 删除操作(需要 v 是可变的)
v.remove(1); // 删除索引1的元素(原2被移除)
println!("删除索引1后: {:?}", v);
v.pop(); // 删除最后一个元素
println!("删除最后一个后: {:?}", v);
v.clear(); // 清空所有元素
println!("清空后: {:?}", v);
}

1.3 容量管理
let mut v = Vec::with_capacity(5);
println!("容量: {}, 长度: {}", v.capacity(), v.len()); // 5, 0
v.push(1); v.push(2);
v.shrink_to_fit(); // 缩减到刚好容纳当前元素
2. HashMap<K, V>:键值对映射
2.1 创建与插入
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert("alice".to_string(), 100);
map.insert("bob".to_string(), 200);
// 批量插入
let pairs = vec![("charlie", 300), ("david", 400)];
for (k, v) in pairs {
map.insert(k.to_string(), v);
}
// 或使用迭代器
let map2: HashMap<_, _> = pairs.into_iter().map(|(k, v)| (k.to_string(), v)).collect();
2.2 查询与更新
// 查询(返回 Option)
if let Some(score) = map.get("alice") {
println!("{}", score);
}
// 不存在时插入默认值
let score = map.entry("eve".to_string()).or_insert(0);
*score += 50;
// 更新现有值
map.entry("alice".to_string()).and_modify(|v| *v += 10);
// 移除
map.remove("bob");
2.3 遍历
for (k, v) in &map {
println!("{}: {}", k, v);
}
for k in map.keys() {
println!("key: {}", k);
}
for v in map.values() {
println!("value: {}", v);
}
3. HashSet:无序集合(去重)
3.1 基本操作
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(1);
set.insert(2);
set.insert(2); // 重复,不会插入
println!("{}", set.contains(&1)); // true
println!("{}", set.len()); // 2
set.remove(&1);
3.2 集合运算
let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
let b: HashSet<_> = [2, 3, 4].iter().cloned().collect();
// 交集
let inter: HashSet<_> = a.intersection(&b).cloned().collect();
println!("{:?}", inter); // {2, 3}
// 并集
let union: HashSet<_> = a.union(&b).cloned().collect();
// 差集
let diff: HashSet<_> = a.difference(&b).cloned().collect();
// 对称差集
let sym_diff: HashSet<_> = a.symmetric_difference(&b).cloned().collect();
4. 迭代器 Iterator:零成本抽象
4.1 基础概念
- 迭代器提供统一的遍历方式,惰性求值(只在消费时才执行),零成本抽象(编译期优化为类似手写循环的性能)。
let v = vec![1, 2, 3, 4, 5];
// 显式迭代
let mut iter = v.iter();
while let Some(val) = iter.next() {
println!("{}", val);
}
// for 循环(自动使用迭代器)
for val in &v {
println!("{}", val);
}
4.2 适配器链(链式调用)
let sum: i32 = (1..=10)
.map(|x| x * 2) // 映射:每个元素乘以2
.filter(|x| x % 3 == 0) // 过滤:只保留能被3整除的
.sum(); // 求和
println!("{}", sum); // 24
// 更多适配器
let doubled: Vec<i32> = vec![1, 2, 3].iter().map(|x| x * 2).collect();
let evens: Vec<_> = (1..10).filter(|x| x % 2 == 0).collect();
let first_5: Vec<_> = (1..).take(5).collect();
let skipped: Vec<_> = (1..10).skip(3).collect();
4.3 消费器(Consumers)
let v = vec![1, 2, 3, 4, 5];
let sum: i32 = v.iter().sum(); // 求和
let product: i32 = v.iter().product(); // 求积
let max = v.iter().max(); // 最大值
let min = v.iter().min(); // 最小值
let count = v.iter().count(); // 计数
let any_greater_than_3 = v.iter().any(|x| *x > 3); // 是否存在满足条件的
let all_positive = v.iter().all(|x| *x > 0); // 是否全部满足条件
// find:找到第一个满足条件的元素
if let Some(val) = v.iter().find(|x| **x > 3) {
println!("{}", val);
}
// collect:收集到集合
let doubled: Vec<i32> = v.iter().map(|x| x * 2).collect();
let map: HashMap<_, _> = v.iter().map(|x| (x, x * 2)).collect();
4.4 常用迭代器适配器速查
| 方法 | 功能 | 示例 |
|---|---|---|
map |
转换每个元素 | `iter.map( |
filter |
过滤元素 | `iter.filter( |
take |
取前n个 | iter.take(5) |
skip |
跳过前n个 | iter.skip(3) |
enumerate |
带索引 | iter.enumerate() |
zip |
组合两个迭代器 | iter1.zip(iter2) |
chain |
连接两个迭代器 | iter1.chain(iter2) |
fold |
累积计算 | iter.fold(0, |acc, x| acc + x) |
reduce |
归约(首元素为初始值) | iter.reduce(|acc, x| acc + x) |
flat_map |
扁平化映射 | iter.flat_map(|x| x.iter()) |
5. 自定义迭代器
实现 Iterator trait:
struct Counter { current: usize, max: usize }
impl Iterator for Counter {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.current < self.max {
self.current += 1;
Some(self.current - 1)
} else {
None
}
}
}
fn main() {
let counter = Counter { current: 0, max: 5 };
for val in counter {
println!("{}", val); // 0, 1, 2, 3, 4
}
}
6. 性能与最佳实践
6.1 Vec 性能提示
- 预分配容量:
Vec::with_capacity(n)避免频繁重分配 - 批量操作:
extend_from_slice比多次push更快 - 迭代而非索引:
for item in &vec比for i in 0..vec.len()更快且更安全
6.2 HashMap 性能提示
- 预分配容量:
HashMap::with_capacity(n)减少重哈希 - 合理选择键类型:
Stringvs&str(所有权 vs 借用) - 使用
entryAPI:避免先查询再插入的两次查找
6.3 迭代器性能
- 链式调用零开销:编译器会内联优化,性能等同手写循环
- 及早求值:
collect()会触发迭代器链的实际执行 - 避免中间集合:多用
Iterator链,少用中间Vec
7. 常见错误与修复
- ❌ 在遍历时修改集合:
for item in &mut vec { vec.push(42); }→ 借用冲突- 修复:先收集索引,或使用
retain/drain
- 修复:先收集索引,或使用
- ❌
HashMap用&str作为键存储String:类型不匹配- 修复:统一键类型,或使用
Borrowtrait
- 修复:统一键类型,或使用
- ❌ 忘记调用
collect():迭代器惰性,必须消费才能执行 - ❌ 移动后继续使用:
let iter = vec.into_iter(); println!("{:?}", vec);→ 所有权已转移
8. 实战练习
- 实现一个函数
group_by<T, K, F>(items: Vec<T>, key_fn: F) -> HashMap<K, Vec<T>>,按某个函数分组。 - 用迭代器实现:找出两个
Vec的交集、并集、差集。 - 自定义迭代器:实现一个
Range,支持for i in Range::new(1, 10, 2)(步长为2)。 - 性能对比:对比
for循环与迭代器链在处理大数据时的性能差异。
小结:
Vec适合顺序存储与随机访问HashMap适合键值映射与快速查找HashSet适合去重与集合运算- 迭代器提供统一、高效、安全的遍历方式,是 Rust 函数式编程的核心工具
下一节 将深入讲解迭代器的高级用法:
flat_map、fold、自定义迭代器、并行迭代(rayon)等。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)