
数据处理的流水线:让集合为你打工
还记得你第一次写循环处理数组的时候吗?大概是这样:
let numbers = vec![, , , , ];
let mut result = Vec::new();
for i in ..numbers.len() {
if numbers[i] % == {
result.push(numbers[i] * );
}
}
是不是感觉……有点啰嗦?而且容易出错(索引越界警告在看着你)。
Rust 的**迭代器(Iterator)**模式让你用更优雅的方式处理集合数据。今天咱们就聊聊这个让代码像流水线一样流畅的神器。
迭代器是一个按需产生值的对象。它不会一次性把所有数据算出来,而是你要一个,它给一个。
生活化类比:
想象你去自助餐厅:
所有迭代器都实现 Iterator 这个 Trait:
trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
说人话:
迭代器只有一个核心方法 next():
Some(value)None就这么简单!
特性 | 说明 | 好处 |
|---|---|---|
惰性 | 不调用就不会执行 | 节省内存和计算 |
零成本 | 编译后和手写循环一样快 | 没有性能损失 |
可组合 | 可以链式调用 | 代码简洁优雅 |
生活化类比:
迭代器就像工厂流水线:
fn main() {
let numbers = vec![, , , , ];
// 三种创建迭代器的方式
let iter1 = numbers.iter(); // 不可变引用
let iter2 = numbers.iter_mut(); // 可变引用
let iter3 = numbers.into_iter(); // 拥有所有权
for num in iter1 {
println!("{}", num); // 只读
}
}
三种方式的区别:
iter():借来看看,不能改iter_mut():借来改改,原数据会变into_iter():拿走,原数据没了fn main() {
let numbers = vec![, , , , , , , , , ];
// 过滤出偶数
let evens: Vec<_> = numbers
.iter()
.filter(|&n| n % == )
.collect();
println!("{:?}", evens); // [2, 4, 6, 8, 10]
}
注意: filter 本身不执行,直到你调用 collect() 才真正开始计算(惰性求值)。
fn main() {
let numbers = vec![, , , , ];
// 每个数平方
let squares: Vec<_> = numbers
.iter()
.map(|&n| n * n)
.collect();
println!("{:?}", squares); // [1, 4, 9, 16, 25]
}
fn main() {
let numbers = vec![, , , , , , , , , ];
// 过滤偶数 -> 平方 -> 收集
let result: Vec<_> = numbers
.iter()
.filter(|&n| n % == ) // 只留偶数
.map(|&n| n * n) // 平方
.collect();
println!("{:?}", result); // [4, 16, 36, 64, 100]
}
看到没?代码像读句子一样自然!
fn main() {
let numbers = vec![, , , , ];
// take: 取前 N 个
let first_three: Vec<_> = numbers
.iter()
.take()
.collect();
println!("{:?}", first_three); // [1, 2, 3]
// skip: 跳过前 N 个
let skip_two: Vec<_> = numbers
.iter()
.skip()
.collect();
println!("{:?}", skip_two); // [3, 4, 5]
// enumerate: 带索引
for (index, value) in numbers.iter().enumerate() {
println!("{}: {}", index, value);
}
// zip: 两个迭代器配对
let letters = vec!['a', 'b', 'c'];
let paired: Vec<_> = numbers.iter().zip(letters.iter()).collect();
println!("{:?}", paired); // [(1, 'a'), (2, 'b'), (3, 'c')]
}
fn main() {
let numbers = vec![, , , , ];
// collect: 收集到集合
let doubled: Vec<_> = numbers.iter().map(|n| n * ).collect();
// sum: 求和
let sum: i32 = numbers.iter().sum();
println!("总和:{}", sum); // 15
// product: 求积
let product: i32 = numbers.iter().product();
println!("乘积:{}", product); // 120
// count: 计数
let count = numbers.iter().filter(|&n| n % == ).count();
println!("偶数个数:{}", count); // 2
// any: 是否有任何一个满足条件
let has_even = numbers.iter().any(|&n| n % == );
println!("有偶数吗?{}", has_even); // true
// all: 是否全部满足条件
let all_positive = numbers.iter().all(|&n| n > );
println!("都是正数吗?{}", all_positive); // true
// find: 找到第一个满足条件的
let first_even = numbers.iter().find(|&n| n % == );
println!("第一个偶数:{:?}", first_even); // Some(2)
}
适配器 vs 消费器:
fn main() {
let numbers = vec![, , , , ];
let iter = numbers.iter();
let sum: i32 = iter.sum(); // ✅ 第一次使用
let count = iter.count(); // ❌ 编译错误!
// 错误信息:use of moved value: `iter`
}
编译器在说什么人话?
"迭代器已经被 sum() 用掉了(调用了 next() 直到 None),不能再用了!"
解决方案:
// 重新创建迭代器
let sum: i32 = numbers.iter().sum();
let count = numbers.iter().count();
fn main() {
let numbers = vec![, , , , ];
// ❌ 编译错误:无法推断类型
let result = numbers.iter().map(|n| n * ).collect();
}
解决方案:
// 显式指定类型
let result: Vec<_> = numbers.iter().map(|n| n * ).collect();
fn main() {
let threshold = ;
let numbers = vec![, , , , , , , , , ];
// ✅ 这样写可以
let result: Vec<_> = numbers
.iter()
.filter(|&n| n > &threshold)
.collect();
println!("{:?}", result); // [6, 7, 8, 9, 10]
}
如果闭包要修改捕获的变量,记得用 mut 和 FnMut。
fn main() {
let numbers = vec![, , , , ];
let iter = numbers.iter();
// ❌ 这样写不行
drop(numbers); // numbers 被删除了
for n in iter { // ❌ 编译错误:借用已释放的数据
println!("{}", n);
}
}
记住: 迭代器只是借用,原数据必须活着。
fn main() {
let transactions = vec![
("Alice", ),
("Bob", ),
("Charlie", ),
("Alice", ),
("Bob", ),
];
// 计算每个人的总金额
use std::collections::HashMap;
let mut totals: HashMap<&str, i32> = HashMap::new();
for &(name, amount) in &transactions {
*totals.entry(name).or_insert() += amount;
}
for (name, total) in &totals {
println!("{}: {}", name, total);
}
}
#[derive(Debug)]
struct Product {
name: String,
price: f64,
in_stock: bool,
}
fn main() {
let products = vec![
Product { name: String::from("Laptop"), price: 999.99, in_stock: true },
Product { name: String::from("Mouse"), price: 29.99, in_stock: false },
Product { name: String::from("Keyboard"), price: 79.99, in_stock: true },
Product { name: String::from("Monitor"), price: 299.99, in_stock: true },
];
// 有货的产品 -> 按价格排序 -> 取前 2 个 -> 收集名字
let cheap_products: Vec<_> = products
.iter()
.filter(|p| p.in_stock)
.map(|p| (p.name.as_str(), p.price))
.collect();
println!("{:?}", cheap_products);
}
// 斐波那契数列迭代器
struct Fibonacci {
current: u32,
next: u32,
}
impl Fibonacci {
fn new() -> Fibonacci {
Fibonacci { current: , next: }
}
}
impl Iterator for Fibonacci {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
let current = self.current;
self.current = self.next;
self.next = current + self.next;
Some(current)
}
}
fn main() {
let fib = Fibonacci::new();
// 取前 10 个斐波那契数
let first_ten: Vec<_> = fib.take().collect();
println!("{:?}", first_ten);
// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
}

金句回顾:
下篇预告:
咱们已经学了模式匹配的基础(match 和 if let),但那只是开胃菜。下篇聊聊模式匹配进阶,看看 Rust 的模式匹配能玩出什么花样——解构、守卫、嵌套模式,让你写出像诗歌一样的代码!