核心特性

第12课:迭代器

🎯 本课目标

掌握Rust迭代器协议、适配器模式、惰性求值和自定义迭代器。

1. Iterator trait

trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}
fn main() {
    let v = vec![1, 2, 3, 4, 5];

    // 手动迭代
    let mut iter = v.iter();
    println!("{:?}", iter.next());  // Some(1)
    println!("{:?}", iter.next());  // Some(2)

    // for循环(最常用)
    for val in &v {
        println!("{}", val);
    }

    // 三种迭代方式
    for val in v.iter() { }       // &T 借用
    for val in v.iter_mut() { }   // &mut T 可变借用
    for val in v.into_iter() { }  // T 获取所有权
}

✅ 编译验证通过

2. 迭代器适配器

fn main() {
    let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    // map — 变换
    let doubled: Vec<i32> = v.iter().map(|x| x * 2).collect();

    // filter — 过滤
    let evens: Vec<&i32> = v.iter().filter(|x| *x % 2 == 0).collect();

    // 链式调用!
    let sum: i32 = v.iter()
        .filter(|x| *x % 2 == 0)    // 偶数
        .map(|x| x * x)              // 平方
        .sum();                       // 求和

    // take / skip
    let first3: Vec<&i32> = v.iter().take(3).collect();
    let skip2: Vec<&i32> = v.iter().skip(2).collect();

    // zip — 合并
    let names = vec!["Alice", "Bob"];
    let scores = vec![95, 87];
    let pairs: Vec<_> = names.iter().zip(scores.iter).collect();

    // flat_map — 展平
    let words = vec!["hello world", "rust lang"];
    let all: Vec<&str> = words.iter()
        .flat_map(|s| s.split_whitespace())
        .collect();

    // enumerate / rev / inspect
    for (i, v) in v.iter().enumerate().rev() {
        println!("[{}] = {}", i, v);
    }
}

✅ 编译验证通过

3. 消费适配器

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

    // collect
    let doubled: Vec<i32> = v.iter().map(|x| x * 2).collect();

    // fold — 通用归约
    let sum = v.iter().fold(0, |acc, x| acc + x);

    // reduce
    let max = v.iter().copied().reduce(i32::max);

    // for_each
    v.iter().for_each(|x| println!("{}", x));

    // count / last / nth
    let count = v.iter().count();
    let last = v.iter().last();
    let third = v.iter().nth(2);
}

✅ 编译验证通过

4. 自定义迭代器

struct Fibonacci {
    curr: u64,
    next: u64,
}

impl Fibonacci {
    fn new() -> Self {
        Fibonacci { curr: 0, next: 1 }
    }
}

impl Iterator for Fibonacci {
    type Item = u64;
    fn next(&mut self) -> Option<Self::Item> {
        let new_next = self.curr + self.next;
        self.curr = self.next;
        self.next = new_next;
        Some(self.curr)
    }
}

fn main() {
    let fibs: Vec<u64> = Fibonacci::new().take(10).collect();
    println!("前10个斐波那契数: {:?}", fibs);

    // 第20个斐波那契数
    let fib20 = Fibonacci::new().nth(19).unwrap();
    println!("F(20) = {}", fib20);
}

✅ 编译验证通过

5. 惰性求值

迭代器适配器是惰性的——只有消费时才执行。这意味着链式调用不会创建中间集合!零成本抽象!

惰性求值内存模型: v.iter().filter(|x| *x > 3).map(|x| x * 2).collect() 不创建中间Vec!每个元素一次通过: 元素1 → filter(不通过) → 丢弃 元素2 → filter(不通过) → 丢弃 元素3 → filter(不通过) → 丢弃 元素4 → filter(通过) → map → 8 → collect 元素5 → filter(通过) → map → 10 → collect 结果: [8, 10] — 无中间分配!

📝 练习题

练习1:单词统计

用迭代器统计文本中每个单词的出现频率。

练习2:质数迭代器

实现一个无限质数迭代器。

练习3:组合迭代器

用迭代器实现全排列生成。

🏆

成就解锁:流式处理者

掌握迭代器——Rust最优雅的抽象之一


📚 扩展阅读

以下资源帮助你深入学习本课主题:

🔑 关键术语回顾

本课涉及的核心概念,确保你理解每一个:

术语说明
所有权Rust内存管理的核心机制,每个值有唯一所有者
借用通过引用访问数据,不获取所有权
生命周期引用有效的范围,编译期分析工具
traitRust的接口/抽象机制,类似其他语言的接口
泛型参数化类型,零成本抽象
模式匹配强大的数据解构和分支机制
零成本抽象高层抽象不引入运行时开销
fearless concurrency编译器保证线程安全

💬 学习建议

  1. 动手编码 — 每个代码示例都在本地运行一遍
  2. 修改实验 — 故意改错代码,看编译器报什么错
  3. 完成练习 — 每课的练习题是巩固知识的关键
  4. 阅读源码 — 看标准库和优秀开源项目的实现
  5. 写项目 — 真正掌握需要构建真实项目

🤔 常见问题

Q: Rust学习曲线真的很陡吗?

A: 前期确实需要适应所有权和借用检查器,但一旦理解了,这些概念会让你的代码更可靠。大多数人2-4周就能上手。

Q: Rust适合什么项目?

A: 系统编程、Web服务、CLI工具、嵌入式、WASM、网络服务、数据库等。基本上需要性能和安全的地方都适合。

Q: 遇到编译错误怎么办?

A: Rust编译器的错误信息非常友好!仔细阅读,通常会指出问题所在和修复建议。也可以用cargo clippy获取更多提示。