本章系统讲解 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 访问与修改

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

// 安全访问
if let Some(val) = v.get(2) {                // 返回 Option<&T>
    println!("{}", val);
}

// 直接索引(越界会panic)
let third = v[2];                             // 3

// 可变借用
if let Some(val) = v.get_mut(2) {
    *val = 99;
}

// 删除
v.remove(1);                                  // 删除索引1,后续元素前移
v.pop();                                      // 删除最后一个
v.clear();                                    // 清空所有元素

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 基础概念

  • 迭代器提供统一的遍历方式,惰性求值(只在消费时才执行),零成本抽象(编译期优化为类似手写循环的性能)。
fn main() {
    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)

use std::collections::HashMap; // 导入HashMap

fn main() {
    let v = vec![1, 2, 3, 4, 5];

    let sum: i32 = v.iter().sum();               // 求和
    // 修复:product需要指定初始值类型,使用fold替代更直观
    let product: i32 = v.iter().fold(1, |acc, &x| acc * x);       // 求积
    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!("第一个大于3的元素: {}", val);
    }

    // collect:收集到集合
    let doubled: Vec<i32> = v.iter().map(|x| x * 2).collect();
    let map: HashMap<_, _> = v.iter().map(|x| (x, x * 2)).collect();

    // 打印结果验证
    println!("求和: {}", sum);
    println!("求积: {}", product);
    println!("最大值: {:?}", max);
    println!("最小值: {:?}", min);
    println!("元素数量: {}", count);
    println!("存在大于3的元素: {}", any_greater_than_3);
    println!("所有元素都是正数: {}", all_positive);
    println!("每个元素乘以2: {:?}", doubled);
    println!("映射集合: {:?}", map);
}
    

在这里插入图片描述

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 &vecfor i in 0..vec.len() 更快且更安全

6.2 HashMap 性能提示

  • 预分配容量HashMap::with_capacity(n) 减少重哈希
  • 合理选择键类型String vs &str(所有权 vs 借用)
  • 使用 entry API:避免先查询再插入的两次查找

6.3 迭代器性能

  • 链式调用零开销:编译器会内联优化,性能等同手写循环
  • 及早求值collect() 会触发迭代器链的实际执行
  • 避免中间集合:多用 Iterator 链,少用中间 Vec

7. 常见错误与修复

  • ❌ 在遍历时修改集合:for item in &mut vec { vec.push(42); } → 借用冲突
    • 修复:先收集索引,或使用 retain/drain
  • HashMap&str 作为键存储 String:类型不匹配
    • 修复:统一键类型,或使用 Borrow trait
  • ❌ 忘记调用 collect():迭代器惰性,必须消费才能执行
  • ❌ 移动后继续使用:let iter = vec.into_iter(); println!("{:?}", vec); → 所有权已转移

8. 实战练习

  1. 实现一个函数 group_by<T, K, F>(items: Vec<T>, key_fn: F) -> HashMap<K, Vec<T>>,按某个函数分组。
  2. 用迭代器实现:找出两个 Vec 的交集、并集、差集。
  3. 自定义迭代器:实现一个 Range,支持 for i in Range::new(1, 10, 2)(步长为2)。
  4. 性能对比:对比 for 循环与迭代器链在处理大数据时的性能差异。

小结

  • Vec 适合顺序存储与随机访问
  • HashMap 适合键值映射与快速查找
  • HashSet 适合去重与集合运算
  • 迭代器提供统一、高效、安全的遍历方式,是 Rust 函数式编程的核心工具

下一节 将深入讲解迭代器的高级用法:flat_mapfold、自定义迭代器、并行迭代(rayon)等。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐