迭代器基础
> 理解迭代器的概念和价值,掌握迭代器的核心抽象和惰性计算机制。
为什么需要迭代器?
迭代器语法
概念名称: 迭代器提供遍历序列的统一抽象,惰性计算。
语法结构:
┌──────────────────────────────────────┐
│ for 元素 in 集合.iter() { ... } │
│ ↑ │
│ 创建迭代器 │
│ │
│ 集合.iter() → 不可变迭代器 │
│ 集合.iter_mut() → 可变迭代器 │
│ 集合.into_iter() → 获取所有权 │
│ │
│ 常用方法: │
│ .map(|x| x * 2) → 转换 │
│ .filter(|x| x > 0) → 过滤 │
│ .collect() → 收集为集合 │
│ .next() → 获取下一个 │
└──────────────────────────────────────┘最简示例
rust
▶ Runfn main() {
let nums = vec![1, 2, 3];
for n in nums.iter() {
println!("{}", n);
}
}统一处理序列数据
rust
▶ Run// 问题:不同类型的集合需要不同的遍历方式
// Vec 使用索引
let v = vec![1, 2, 3];
for i in 0..v.len() {
println!("{}", v[i]);
}
// HashMap 需要 iter()
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert("a", 1);
for (k, v) in map.iter() {
println!("{}: {}", k, v);
}
// 解决方案:使用迭代器统一处理
for item in v.iter() {
println!("{}", item);
}
for item in map.iter() {
println!("{}: {}", item.0, item.1);
}惰性计算的优势
rust
▶ Run// 问题:立即计算可能浪费资源
// 方案 1: eagerly 计算(可能浪费)
let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
// 即使只需要第一个元素,也计算了所有
// 方案 2:使用迭代器惰性计算
let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let mut doubled_iter = numbers.iter().map(|x| x * 2);
// 此时还没有计算!
// 只在需要时计算
let first = doubled_iter.next(); // 只计算第一个
println!("{:?}", first); // Some(2)迭代器的核心优势
┌─────────────────────────────────────────────────────┐
│ 迭代器的优势 │
├─────────────────────────────────────────────────────┤
│ │
│ 1. 统一抽象 │
│ • 任何序列都可以用相同方式处理 │
│ • Vec, HashMap, 数组,自定义类型 │
│ • 一致的操作接口 │
│ │
│ 2. 惰性计算 │
│ • 只有在消费时才执行 │
│ • 可以处理无限序列 │
│ • 节省内存和 CPU │
│ │
│ 3. 链式组合 │
│ • 多个操作可以链式组合 │
│ • 代码简洁易读 │
│ • 编译器可以优化 │
│ │
│ 4. 零成本抽象 │
│ • 编译时优化 │
│ • 与手写循环性能相同 │
│ • 无额外运行时开销 │
│ │
└─────────────────────────────────────────────────────┘
---
## 小结
- 迭代器提供遍历序列的统一抽象,惰性计算
- 三种创建方式:iter()、iter_mut()、into_iter()
- 统一抽象、惰性计算、链式组合、零成本抽象四大优势
- 惰性计算只在消费时执行,节省资源
- 任何实现了 Iterator trait 的类型都可以迭代
## 练习题
详见:[练习题](../../exercises/19-iterators)