Rust 迭代器
Iterator trait、惰性适配器、消费者与 collect;零成本抽象下的集合处理主路径。
#concept
#growing
#dev
#rust
[!info] related notes
Rust 迭代器
这个概念为什么出现
处理集合的标准方式不应是满屏下标。
Iterator 把“如何产生下一个元素”抽象出来,适配器(map/filter)惰性组合,消费者(collect/sum)触发执行。
[!abstract] 一句话理解 实现
Iterator的类型可产生一系列Item;适配器惰性变换流;collect等消费者强制求值。
最小可运行示例
场景:订单金额——筛选大额并计算税费后总额
财务任务:金额列表中筛 >=100 的订单,加 10% 税后求和。
// 业务意图:筛选大额订单并计税汇总。
// 教学点:iter/map/filter/sum 惰性链;闭包捕获。
fn main() {
let amounts = [50_u32, 120, 80, 200];
let taxed_total: u64 = amounts
.iter()
.copied()
.filter(|a| *a >= 100)
.map(|a| u64::from(a) + u64::from(a) / 10) // 每笔按整数单位向下取整
.sum();
println!("taxed_total={taxed_total}");
}
建议运行:cargo run
期望输出:
taxed_total=352
(120→132,200→220,和 352)。此处四个 u32 输入用 u64 汇总足够;任意长度的金额流仍需检查总和溢出,并明确按笔还是汇总后舍入。
结合场景再看三个关注点
- 中间步骤不建临时 Vec(直到需要)
- 可读的数据管道
- 类型由
sum/collect注解引导
核心概念与准确模型
trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
iter:&Titer_mut:&mut T- 拥有的 Vec
上 into_iter()产出 T;&Vec<T>上则产出 &T,IntoIterator 不统一等于移动元素
map/filter 的闭包随消费执行,构造适配器不会遍历全部输入;但调用前的参数表达式仍会求值。for、next、sum、find 等都可消费,不必先 collect。
Iterator 本身不保证返回 None 后永远结束,需此保证可用 fuse / FusedIterator。collect::<Result<Vec<_>, E>>() 在首个 Err 短路,后续元素不再处理;此前副作用不会回滚。
设计动机
- 统一遍历协议
- 优化友好的惰性融合(实现可优化)
- 函数式表达力 + 系统性能
边界与误区
- 忘了消费者导致“没执行”
- 在迭代同一集合时修改结构需遵守借用
- 无限迭代器要
take
[!warning] 常见误区:以为 map 立刻生成新 Vec 默认惰性;
collect才物化。
工程实践
- 优先迭代器链表达变换
- 热路径看汇编/基准,不盲信
- 复杂链抽函数命名
- 错误用
collect::<Result<Vec<_>,_>>()模式
本节总结
- Iterator + 适配器 + 消费者
- 惰性默认
- 与闭包深度结合
自测题
iter与into_iter区别?- 为何需要
collect类型注解?
参考答案
- Vec 的 iter 借用元素;IntoIterator 的产出取决于接收者是拥有值还是引用。
- 可收集进多种目标类型,编译器需知道目标。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| The Book — Iterators | 官方书 | 迭代器 |
| std::iter::Iterator | 标准库 | API |