Rust 迭代器(Iterator)概念与代码示例
📚 一、迭代器核心概念
1. 迭代器是什么?
迭代器是 Rust 中一种惰性求值的序列处理抽象,它允许你遍历集合(如数组、Vec、HashMap 等)中的元素,而无需关心底层数据结构的具体实现。
2. 核心特点
- 惰性求值:只有在需要时才会计算下一个元素
- 零成本抽象:编译器优化后几乎没有运行时开销
- 安全:编译时检查,避免越界访问
- 可组合:可以链式调用多个迭代器适配器
🔧 二、基本迭代器用法
1. 创建迭代器
fn basic_iterators() {
// 1. 数组/切片迭代器
let arr = [1, 2, 3, 4, 5];
let arr_iter = arr.iter(); // 产生 &i32
let arr_iter_mut = arr.iter_mut(); // 产生 &mut i32
let arr_into_iter = arr.into_iter(); // 产生 i32(消耗所有权)
// 2. Vec 迭代器
let vec = vec![1, 2, 3, 4, 5];
let vec_iter = vec.iter();
let vec_into_iter = vec.into_iter(); // 消耗 vec
// 3. Range 迭代器
let range = 0..10; // 0 到 9
let range_inclusive = 0..=10; // 0 到 10
// 4. 字符串迭代器
let s = "hello";
let chars_iter = s.chars(); // Unicode 标量值
let bytes_iter = s.bytes(); // 字节
let lines_iter = s.lines(); // 行
let split_iter = s.split(' '); // 分割
}
2. 使用迭代器
fn using_iterators() {
let numbers = vec![1, 2, 3, 4, 5];
// 方法1: for 循环(自动调用 into_iter)
for num in &numbers {
println!("{}", num);
}
// 方法2: 手动调用 next()
let mut iter = numbers.iter();
// 逐个获取元素
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), Some(&3));
assert_eq!(iter.next(), Some(&4));
assert_eq!(iter.next(), Some(&5));
assert_eq!(iter.next(), None); // 遍历结束
// 方法3: 使用 while let
let mut iter = numbers.iter();
while let Some(num) = iter.next() {
println!("{}", num);
}
}
🎯 三、迭代器适配器
1. 转换适配器
fn transform_adapters() {
let numbers = vec![1, 2, 3, 4, 5];
// 1. map - 转换每个元素
let squares: Vec<_> = numbers.iter()
.map(|x| x * x)
.collect();
println!("Squares: {:?}", squares); // [1, 4, 9, 16, 25]
// 2. filter - 过滤元素
let evens: Vec<_> = numbers.iter()
.filter(|&&x| x % 2 == 0)
.copied()
.collect();
println!("Evens: {:?}", evens); // [2, 4]
// 3. filter_map - 过滤并转换
let parsed: Vec<i32> = vec!["1", "2", "three", "4", "5"]
.iter()
.filter_map(|s| s.parse().ok())
.collect();
println!("Parsed: {:?}", parsed); // [1, 2, 4, 5]
// 4. flatten - 展平嵌套迭代器
let nested = vec![vec![1, 2], vec![3, 4], vec![5]];
let flat: Vec<_> = nested.into_iter()
.flatten()
.collect();
println!("Flattened: {:?}", flat); // [1, 2, 3, 4, 5]
// 5. flat_map - 映射后展平
let words = vec!["hello", "world"];
let chars: Vec<char> = words.iter()
.flat_map(|s| s.chars())
.collect();
println!("Chars: {:?}", chars);
}
2. 消费适配器
fn consuming_adapters() {
let numbers = vec![1, 2, 3, 4, 5];
// 1. collect - 收集到集合
let doubled: Vec<i32> = numbers.iter()
.map(|x| x * 2)
.collect();
// 收集到不同容器
use std::collections::{HashSet, HashMap};
let set: HashSet<_> = numbers.iter().copied().collect();
let map: HashMap<_, _> = numbers.iter()
.map(|&x| (x, x.to_string()))
.collect();
// 2. fold - 累积计算
let sum = numbers.iter().fold(0, |acc, &x| acc + x);
println!("Sum: {}", sum); // 15
let product = numbers.iter().fold(1, |acc, &x| acc * x);
println!("Product: {}", product); // 120
// 3. reduce - 与 fold 类似,但使用第一个元素作为初始值
let max = numbers.iter().copied().reduce(|acc, x| acc.max(x));
println!("Max: {:?}", max); // Some(5)
// 4. for_each - 对每个元素执行操作
numbers.iter().for_each(|x| println!("Number: {}", x));
// 5. all / any - 检查所有/任意元素满足条件
let all_positive = numbers.iter().all(|&x| x > 0);
println!("All positive: {}", all_positive); // true
let any_negative = numbers.iter().any(|&x| x < 0);
println!("Any negative: {}", any_negative); // false
// 6. find / position - 查找元素
let first_even = numbers.iter().find(|&&x| x % 2 == 0);
println!("First even: {:?}", first_even); // Some(&2)
let pos = numbers.iter().position(|&x| x == 3);
println!("Position of 3: {:?}", pos); // Some(2)
// 7. count - 计数
let count = numbers.iter().count();
println!("Count: {}", count); // 5
// 8. sum / product - 求和/求积
let sum: i32 = numbers.iter().sum();
println!("Sum: {}", sum); // 15
let product: i32 = numbers.iter().product();
println!("Product: {}", product); // 120
// 9. min / max - 最小/最大值
let min = numbers.iter().min();
println!("Min: {:?}", min); // Some(&1)
let max = numbers.iter().max();
println!("Max: {:?}", max); // Some(&5)
// 10. nth - 获取第n个元素
let third = numbers.iter().nth(2);
println!("Third: {:?}", third); // Some(&3)
// 11. last - 获取最后一个元素
let last = numbers.iter().last();
println!("Last: {:?}", last); // Some(&5)
}
3. 组合适配器
fn combinatory_adapters() {
let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// 1. take - 取前n个元素
let first_three: Vec<_> = numbers.iter()
.take(3)
.copied()
.collect();
println!("First three: {:?}", first_three); // [1, 2, 3]
// 2. skip - 跳过前n个元素
let after_five: Vec<_> = numbers.iter()
.skip(5)
.copied()
.collect();
println!("After five: {:?}", after_five); // [6, 7, 8, 9, 10]
// 3. take_while - 一直取元素直到条件不满足
let less_than_five: Vec<_> = numbers.iter()
.take_while(|&&x| x < 5)
.copied()
.collect();
println!("Less than five: {:?}", less_than_five); // [1, 2, 3, 4]
// 4. skip_while - 一直跳过元素直到条件不满足
let from_five: Vec<_> = numbers.iter()
.skip_while(|&&x| x < 5)
.copied()
.collect();
println!("From five: {:?}", from_five); // [5, 6, 7, 8, 9, 10]
// 5. step_by - 步进
let even_indices: Vec<_> = numbers.iter()
.step_by(2)
.copied()
.collect();
println!("Step by 2: {:?}", even_indices); // [1, 3, 5, 7, 9]
// 6. chain - 连接两个迭代器
let part1 = vec![1, 2, 3];
let part2 = vec![4, 5, 6];
let chained: Vec<_> = part1.iter()
.chain(part2.iter())
.copied()
.collect();
println!("Chained: {:?}", chained); // [1, 2, 3, 4, 5, 6]
// 7. zip - 将两个迭代器压缩成一个
let names = vec!["Alice", "Bob", "Charlie"];
let ages = vec![25, 30, 35];
let zipped: Vec<_> = names.iter()
.zip(ages.iter())
.collect();
println!("Zipped: {:?}", zipped);
// [("Alice", 25), ("Bob", 30), ("Charlie", 35)]
// 8. enumerate - 添加索引
for (index, value) in numbers.iter().enumerate() {
println!("{}: {}", index, value);
}
// 9. cycle - 无限循环迭代器
let repeating: Vec<_> = vec![1, 2, 3].into_iter()
.cycle()
.take(10)
.collect();
println!("Cycled: {:?}", repeating); // [1, 2, 3, 1, 2, 3, 1, 2, 3, 1]
// 10. rev - 反向迭代
let reversed: Vec<_> = numbers.iter().rev().copied().collect();
println!("Reversed: {:?}", reversed); // [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
}
🎨 四、自定义迭代器
1. 为自定义类型实现迭代器
struct Counter {
count: u32,
max: u32,
}
impl Counter {
fn new(max: u32) -> Self {
Counter { count: 0, max }
}
}
// 实现 Iterator trait
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.count < self.max {
self.count += 1;
Some(self.count)
} else {
None
}
}
}
// 使用自定义迭代器
fn custom_iterator() {
let counter = Counter::new(5);
// 使用迭代器方法
for num in counter {
println!("{}", num); // 1, 2, 3, 4, 5
}
// 可以组合使用适配器
let sum: u32 = Counter::new(10)
.filter(|x| x % 2 == 0)
.sum();
println!("Sum of evens: {}", sum); // 30
}
2. 实现 IntoIterator
struct Matrix {
data: Vec<Vec<i32>>,
rows: usize,
cols: usize,
}
impl Matrix {
fn new(rows: usize, cols: usize) -> Self {
let data = vec![vec![0; cols]; rows];
Matrix { data, rows, cols }
}
fn set(&mut self, row: usize, col: usize, value: i32) {
if row < self.rows && col < self.cols {
self.data[row][col] = value;
}
}
}
// 实现行优先迭代
impl IntoIterator for Matrix {
type Item = i32;
type IntoIter = std::vec::IntoIter<i32>;
fn into_iter(self) -> Self::IntoIter {
self.data.into_iter()
.flatten()
.collect::<Vec<i32>>()
.into_iter()
}
}
// 实现不可变引用迭代
impl<'a> IntoIterator for &'a Matrix {
type Item = &'a i32;
type IntoIter = std::vec::IntoIter<&'a i32>;
fn into_iter(self) -> Self::IntoIter {
self.data.iter()
.flatten()
.collect::<Vec<&i32>>()
.into_iter()
}
}
// 实现可变引用迭代
impl<'a> IntoIterator for &'a mut Matrix {
type Item = &'a mut i32;
type IntoIter = std::vec::IntoIter<&'a mut i32>;
fn into_iter(self) -> Self::IntoIter {
self.data.iter_mut()
.flat_map(|row| row.iter_mut())
.collect::<Vec<&mut i32>>()
.into_iter()
}
}
fn test_matrix_iter() {
let mut matrix = Matrix::new(2, 3);
// 初始化矩阵
for i in 0..2 {
for j in 0..3 {
matrix.set(i, j, (i * 3 + j) as i32);
}
}
// 使用 for 循环(消耗所有权)
for value in matrix {
print!("{} ", value); // 0 1 2 3 4 5
}
println!();
// 重新创建
let mut matrix = Matrix::new(2, 3);
for i in 0..2 {
for j in 0..3 {
matrix.set(i, j, (i * 3 + j) as i32);
}
}
// 使用不可变引用
for value in &matrix {
print!("{} ", value); // 0 1 2 3 4 5
}
println!();
// 使用可变引用
for value in &mut matrix {
*value *= 2;
}
// 检查修改结果
for value in &matrix {
print!("{} ", value); // 0 2 4 6 8 10
}
}
⚡ 五、高级迭代器模式
1. 惰性求值示例
fn lazy_evaluation() {
let numbers = vec![1, 2, 3, 4, 5];
// 创建迭代器但不立即求值
let iterator = numbers.iter()
.map(|x| {
println!("Mapping: {}", x);
x * 2
})
.filter(|x| {
println!("Filtering: {}", x);
x > &4
});
println!("Iterator created, but not consumed yet");
// 只有在消费时才会执行
let result: Vec<_> = iterator.collect();
println!("Result: {:?}", result);
// 输出:
// Iterator created, but not consumed yet
// Mapping: 1
// Filtering: 2
// Mapping: 2
// Filtering: 4
// Mapping: 3
// Filtering: 6
// Mapping: 4
// Filtering: 8
// Mapping: 5
// Filtering: 10
// Result: [6, 8, 10]
}
2. 迭代器性能优化
fn iterator_performance() {
use std::time::Instant;
let data: Vec<i32> = (0..1_000_000).collect();
// 方法1: 传统循环
let start = Instant::now();
let mut sum1 = 0;
for &x in &data {
if x % 2 == 0 {
sum1 += x;
}
}
let duration1 = start.elapsed();
println!("Loop sum: {} in {:?}", sum1, duration1);
// 方法2: 迭代器链
let start = Instant::now();
let sum2: i32 = data.iter()
.filter(|&&x| x % 2 == 0)
.sum();
let duration2 = start.elapsed();
println!("Iterator sum: {} in {:?}", sum2, duration2);
// 方法3: 优化后的迭代器
let start = Instant::now();
let sum3: i32 = data.iter()
.copied()
.filter(|&x| x % 2 == 0)
.sum();
let duration3 = start.elapsed();
println!("Optimized iterator: {} in {:?}", sum3, duration3);
}
3. 并行迭代器(Rayon)
#[cfg(feature = "rayon")]
fn parallel_iterators() {
use rayon::prelude::*;
let data: Vec<i32> = (0..1_000_000).collect();
// 顺序迭代器
let start = std::time::Instant::now();
let sum_seq: i32 = data.iter().sum();
let duration_seq = start.elapsed();
// 并行迭代器
let start = std::time::Instant::now();
let sum_par: i32 = data.par_iter().sum();
let duration_par = start.elapsed();
println!("Sequential sum: {} in {:?}", sum_seq, duration_seq);
println!("Parallel sum: {} in {:?}", sum_par, duration_par);
// 更多并行操作
let squares: Vec<_> = data.par_iter()
.map(|x| x * x)
.collect();
let max = data.par_iter().max();
let min = data.par_iter().min();
// 并行 filter
let evens: Vec<_> = data.par_iter()
.filter(|&&x| x % 2 == 0)
.copied()
.collect();
}
4. 无限迭代器
fn infinite_iterators() {
use std::iter;
// 1. repeat - 无限重复一个值
let mut ones = iter::repeat(1);
assert_eq!(ones.next(), Some(1));
assert_eq!(ones.next(), Some(1));
// 永无止境...
// 2. repeat_with - 无限重复调用闭包
let mut rng = iter::repeat_with(rand::random::<u8>);
let rand_num = rng.next().unwrap();
// 3. successors - 基于前一个值生成下一个值
let powers_of_two = iter::successors(Some(1u32), |&n| n.checked_mul(2));
let first_ten: Vec<_> = powers_of_two.take(10).collect();
println!("Powers of two: {:?}", first_ten);
// 4. 斐波那契数列
let fibonacci = iter::successors(Some((0u32, 1u32)), |&(a, b)| Some((b, a + b)))
.map(|(a, _)| a);
let fib_10: Vec<_> = fibonacci.take(10).collect();
println!("Fibonacci: {:?}", fib_10);
}
📊 六、实用工具函数
1. 迭代器工具函数
fn iterator_utilities() {
// 1. peekable - 查看下一个元素而不消耗
let mut numbers = vec![1, 2, 3].into_iter().peekable();
if let Some(peeked) = numbers.peek() {
println!("Next will be: {}", peeked);
}
// 2. fuse - 在 None 后永远返回 None
let mut iter = vec![Some(1), Some(2), None, Some(3)].into_iter().fuse();
while let Some(item) = iter.next() {
println!("Item: {:?}", item);
}
// 3. inspect - 检查但不修改元素
let sum: i32 = vec![1, 2, 3, 4, 5]
.iter()
.inspect(|&x| println!("Processing: {}", x))
.filter(|&&x| x % 2 == 0)
.inspect(|&x| println!("Filtered: {}", x))
.sum();
// 4. scan - 带状态的映射
let running_total: Vec<i32> = vec![1, 2, 3, 4, 5]
.iter()
.scan(0, |state, &x| {
*state += x;
Some(*state)
})
.collect();
println!("Running total: {:?}", running_total);
// 5. partition - 根据条件分割
let (even, odd): (Vec<_>, Vec<_>) = (1..=10).partition(|&x| x % 2 == 0);
println!("Evens: {:?}, Odds: {:?}", even, odd);
// 6. unzip - 将元组迭代器分解
let pairs = vec![(1, 'a'), (2, 'b'), (3, 'c')];
let (numbers, letters): (Vec<_>, Vec<_>) = pairs.into_iter().unzip();
println!("Numbers: {:?}, Letters: {:?}", numbers, letters);
}
2. 自定义适配器
struct Window<I: Iterator> {
iter: I,
size: usize,
buffer: Vec<I::Item>,
}
impl<I> Window<I>
where
I: Iterator,
I::Item: Clone,
{
fn new(iter: I, size: usize) -> Self {
Window {
iter,
size,
buffer: Vec::with_capacity(size),
}
}
}
impl<I> Iterator for Window<I>
where
I: Iterator,
I::Item: Clone,
{
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
// 填充缓冲区
while self.buffer.len() < self.size {
if let Some(item) = self.iter.next() {
self.buffer.push(item);
} else {
break;
}
}
if self.buffer.len() == self.size {
let window = self.buffer.clone();
self.buffer.remove(0);
Some(window)
} else {
None
}
}
}
// 扩展 Iterator trait
trait WindowExt: Iterator {
fn window(self, size: usize) -> Window<Self>
where
Self: Sized,
Self::Item: Clone,
{
Window::new(self, size)
}
}
impl<I: Iterator> WindowExt for I {}
// 使用自定义窗口适配器
fn test_window() {
let data = vec![1, 2, 3, 4, 5, 6];
for window in data.into_iter().window(3) {
println!("Window: {:?}", window);
}
// 输出:
// Window: [1, 2, 3]
// Window: [2, 3, 4]
// Window: [3, 4, 5]
// Window: [4, 5, 6]
}
🧪 七、实战案例
1. 数据处理管道
struct DataPoint {
timestamp: String,
value: f64,
category: String,
}
fn data_processing_pipeline() -> Result<(), Box<dyn std::error::Error>> {
// 模拟数据
let data = vec![
DataPoint { timestamp: "2023-01-01 10:00".to_string(), value: 100.0, category: "A".to_string() },
DataPoint { timestamp: "2023-01-01 11:00".to_string(), value: 200.0, category: "B".to_string() },
DataPoint { timestamp: "2023-01-01 12:00".to_string(), value: 150.0, category: "A".to_string() },
DataPoint { timestamp: "2023-01-01 13:00".to_string(), value: 300.0, category: "C".to_string() },
DataPoint { timestamp: "2023-01-01 14:00".to_string(), value: 250.0, category: "B".to_string() },
];
// 复杂的数据处理管道
let result: Vec<_> = data.into_iter()
// 过滤有效数据
.filter(|point| point.value > 0.0)
// 解析时间戳
.map(|point| {
let datetime = chrono::NaiveDateTime::parse_from_str(
&point.timestamp, "%Y-%m-%d %H:%M"
).ok();
(datetime, point)
})
.filter_map(|(datetime, point)| datetime.map(|dt| (dt, point)))
// 按类别分组
.fold(std::collections::HashMap::new(), |mut acc, (datetime, point)| {
acc.entry(point.category.clone())
.or_insert_with(Vec::new)
.push((datetime, point.value));
acc
})
.into_iter()
// 计算每个类别的统计信息
.map(|(category, values)| {
let count = values.len();
let sum: f64 = values.iter().map(|(_, v)| v).sum();
let avg = sum / count as f64;
let max = values.iter().map(|(_, v)| v).fold(f64::NEG_INFINITY, |a, &b| a.max(b));
let min = values.iter().map(|(_, v)| v).fold(f64::INFINITY, |a, &b| a.min(b));
(category, count, avg, min, max)
})
.collect();
println!("{:<10} {:<6} {:<10} {:<10} {:<10}",
"Category", "Count", "Average", "Min", "Max");
for (category, count, avg, min, max) in result {
println!("{:<10} {:<6} {:<10.2} {:<10.2} {:<10.2}",
category, count, avg, min, max);
}
Ok(())
}
2. 文件处理
fn file_processing_with_iterators() -> Result<(), Box<dyn std::error::Error>> {
use std::fs;
use std::io::{BufRead, BufReader};
// 读取文件并处理
let file = fs::File::open("data.txt")?;
let reader = BufReader::new(file);
// 使用迭代器处理文件
let result: Vec<_> = reader.lines()
.filter_map(Result::ok) // 忽略I/O错误
.enumerate() // 添加行号
.skip(1) // 跳过标题行
.filter(|(_, line)| !line.trim().is_empty()) // 跳过空行
.map(|(i, line)| (i + 2, line)) // 调整行号(从标题行后开始)
.filter_map(|(line_num, line)| {
let parts: Vec<&str> = line.split(',').collect();
if parts.len() == 3 {
let name = parts[0].trim().to_string();
let age = parts[1].trim().parse::<u32>().ok()?;
let score = parts[2].trim().parse::<f64>().ok()?;
Some((line_num, name, age, score))
} else {
println!("Warning: Invalid format at line {}", line_num);
None
}
})
.filter(|&(_, _, age, _)| age >= 18) // 只保留成年人
.collect();
// 输出结果
for (line_num, name, age, score) in &result {
println!("Line {}: {} ({} years) scored {:.2}",
line_num, name, age, score);
}
// 计算统计信息
if !result.is_empty() {
let total = result.len();
let avg_age = result.iter().map(|&(_, _, age, _)| age as f64).sum::<f64>() / total as f64;
let avg_score = result.iter().map(|&(_, _, _, score)| score).sum::<f64>() / total as f64;
let max_score = result.iter().map(|&(_, _, _, score)| score).fold(f64::NEG_INFINITY, f64::max);
println!("\nStatistics:");
println!("Total records: {}", total);
println!("Average age: {:.1}", avg_age);
println!("Average score: {:.2}", avg_score);
println!("Max score: {:.2}", max_score);
}
Ok(())
}
3. Web API 调用
#[cfg(feature = "reqwest")]
async fn api_pagination_with_iterators() -> Result<(), Box<dyn std::error::Error>> {
use reqwest;
use serde::Deserialize;
use futures::stream::{self, StreamExt};
#[derive(Debug, Deserialize)]
struct ApiResponse {
items: Vec<Item>,
total: u32,
page: u32,
per_page: u32,
}
#[derive(Debug, Deserialize)]
struct Item {
id: u32,
name: String,
value: f64,
}
// 模拟分页API
let client = reqwest::Client::new();
let base_url = "https://api.example.com/items";
// 首先获取第一页以了解总页数
let first_page: ApiResponse = client
.get(base_url)
.query(&[("page", 1)])
.send()
.await?
.json()
.await?;
let total_pages = (first_page.total as f64 / first_page.per_page as f64).ceil() as u32;
// 创建页数迭代器
let pages = 1..=total_pages;
// 使用流并行获取所有页面
let all_items: Vec<Item> = stream::iter(pages)
.map(|page| {
let client = &client;
let url = base_url.to_string();
async move {
let response: ApiResponse = client
.get(&url)
.query(&[("page", page)])
.send()
.await?
.json()
.await?;
Ok::<_, reqwest::Error>(response.items)
}
})
.buffer_unordered(5) // 并发5个请求
.filter_map(|result| async {
match result {
Ok(items) => Some(items),
Err(e) => {
eprintln!("Request failed: {}", e);
None
}
}
})
.flat_map(|items| stream::iter(items))
.collect()
.await;
// 处理数据
let total_value: f64 = all_items.iter()
.map(|item| item.value)
.sum();
let avg_value = total_value / all_items.len() as f64;
let top_items: Vec<_> = all_items.into_iter()
.sorted_by(|a, b| b.value.partial_cmp(&a.value).unwrap())
.take(10)
.collect();
println!("Total items: {}", all_items.len());
println!("Total value: {:.2}", total_value);
println!("Average value: {:.2}", avg_value);
println!("Top 10 items:");
for item in top_items {
println!(" {}: {:.2}", item.name, item.value);
}
Ok(())
}
📋 八、最佳实践总结
1. 选择正确的迭代器方法
| 场景 | 推荐方法 | 原因 |
|---|---|---|
| 简单遍历 | for item in &collection |
最简洁 |
| 需要索引 | for (i, item) in collection.iter().enumerate() |
需要索引时 |
| 过滤 | filter() + collect() |
链式调用清晰 |
| 映射 | map() + collect() |
函数式风格 |
| 查找 | find() / position() |
找到即停止 |
| 存在性检查 | any() / all() |
语义明确 |
| 聚合计算 | fold() / reduce() |
灵活 |
| 大文件处理 | 流式迭代器 | 内存友好 |
2. 性能优化建议
fn optimization_tips() {
let data = vec![1, 2, 3, 4, 5];
// ✅ 避免不必要的 collect()
// 坏做法:
let filtered: Vec<_> = data.iter()
.filter(|&&x| x % 2 == 0)
.collect();
let doubled: Vec<_> = filtered.iter()
.map(|&x| x * 2)
.collect();
// 好做法:
let result: Vec<_> = data.iter()
.filter(|&&x| x % 2 == 0)
.map(|&x| x * 2)
.collect();
// ✅ 使用 Iterator::copied() 而不是 map(|&x| x)
// 坏做法:
let copy1: Vec<_> = data.iter().map(|&x| x).collect();
// 好做法:
let copy2: Vec<_> = data.iter().copied().collect();
// ✅ 大数据集考虑使用迭代器适配器
let large_data: Vec<i32> = (0..1_000_000).collect();
// 链式迭代器(惰性求值,内存友好)
let processed: Vec<i32> = large_data.iter()
.filter(|&&x| x % 2 == 0)
.map(|&x| x * 2)
.take(100) // 只处理前100个
.collect();
// ✅ 使用 Iterator::by_ref() 避免消耗迭代器
let mut iter = data.iter();
let first_two: Vec<_> = iter.by_ref().take(2).collect();
let rest: Vec<_> = iter.collect(); // 可以继续使用
}
3. 常见陷阱与解决方案
fn common_pitfalls() {
// ❌ 陷阱1:多次消费同一个迭代器
let numbers = vec![1, 2, 3];
let iter = numbers.iter();
let sum1: i32 = iter.sum();
// let sum2: i32 = iter.sum(); // ❌ 编译错误:iter 已被消费
// ✅ 解决方案:重新创建迭代器
let sum2: i32 = numbers.iter().sum();
// ❌ 陷阱2:在闭包中意外捕获变量
let mut counter = 0;
let numbers = vec![1, 2, 3];
// 这可能会产生意外的结果
let result: Vec<_> = numbers.iter()
.map(|x| {
counter += 1; // 修改外部状态
x + counter
})
.collect();
// ✅ 解决方案:使用 fold 或 scan
let (result, _) = numbers.iter()
.fold((Vec::new(), 0), |(mut acc, mut counter), &x| {
counter += 1;
acc.push(x + counter);
(acc, counter)
});
// ❌ 陷阱3:无限迭代器忘记限制
use std::iter;
// let infinite: Vec<_> = iter::repeat(1).collect(); // ❌ 永远不会结束
// ✅ 解决方案:使用 take
let limited: Vec<_> = iter::repeat(1).take(10).collect();
// ❌ 陷阱4:迭代器适配器顺序错误
let data = vec!["1", "2", "three", "4", "5"];
// 坏顺序:先 map 后 filter
let bad: Vec<_> = data.iter()
.map(|s| s.parse::<i32>()) // 产生 Result
.filter(|r| r.is_ok()) // 过滤 Ok
.map(|r| r.unwrap()) // 解包
.collect();
// ✅ 好顺序:先 filter 后 map
let good: Vec<_> = data.iter()
.filter_map(|s| s.parse().ok()) // 合并操作
.collect();
}
📦 完整示例:学生成绩处理系统
#[derive(Debug, Clone)]
struct Student {
id: u32,
name: String,
age: u8,
scores: Vec<f32>,
}
impl Student {
fn average_score(&self) -> f32 {
if self.scores.is_empty() {
0.0
} else {
self.scores.iter().sum::<f32>() / self.scores.len() as f32
}
}
fn has_passed(&self, passing_grade: f32) -> bool {
self.average_score() >= passing_grade
}
}
struct GradeBook {
students: Vec<Student>,
}
impl GradeBook {
fn new() -> Self {
GradeBook { students: Vec::new() }
}
fn add_student(&mut self, student: Student) {
self.students.push(student);
}
// 使用迭代器的各种方法
fn statistics(&self) -> Statistics {
let scores: Vec<f32> = self.students.iter()
.map(|s| s.average_score())
.collect();
let count = scores.len();
if count == 0 {
return Statistics::default();
}
let sum: f32 = scores.iter().sum();
let avg = sum / count as f32;
let min = scores.iter().fold(f32::INFINITY, |a, &b| a.min(b));
let max = scores.iter().fold(f32::NEG_INFINITY, |a, &b| a.max(b));
// 计算标准差
let variance: f32 = scores.iter()
.map(|&score| (score - avg).powi(2))
.sum::<f32>() / count as f32;
let std_dev = variance.sqrt();
Statistics {
count,
average: avg,
min,
max,
std_dev,
}
}
fn top_students(&self, n: usize) -> Vec<&Student> {
self.students.iter()
.sorted_by(|a, b| {
b.average_score()
.partial_cmp(&a.average_score())
.unwrap()
})
.take(n)
.collect()
}
fn failing_students(&self, passing_grade: f32) -> Vec<&Student> {
self.students.iter()
.filter(|s| !s.has_passed(passing_grade))
.collect()
}
fn group_by_age(&self) -> std::collections::HashMap<u8, Vec<&Student>> {
self.students.iter()
.fold(
std::collections::HashMap::new(),
|mut map, student| {
map.entry(student.age)
.or_insert_with(Vec::new)
.push(student);
map
}
)
}
fn search_students<F>(&self, predicate: F) -> Vec<&Student>
where
F: Fn(&&Student) -> bool,
{
self.students.iter()
.filter(predicate)
.collect()
}
}
#[derive(Debug, Default)]
struct Statistics {
count: usize,
average: f32,
min: f32,
max: f32,
std_dev: f32,
}
fn main() {
// 创建示例数据
let mut gradebook = GradeBook::new();
gradebook.add_student(Student {
id: 1,
name: "Alice".to_string(),
age: 20,
scores: vec![85.0, 90.0, 88.0],
});
gradebook.add_student(Student {
id: 2,
name: "Bob".to_string(),
age: 21,
scores: vec![70.0, 75.0, 65.0],
});
gradebook.add_student(Student {
id: 3,
name: "Charlie".to_string(),
age: 20,
scores: vec![95.0, 92.0, 98.0],
});
gradebook.add_student(Student {
id: 4,
name: "Diana".to_string(),
age: 22,
scores: vec![60.0, 55.0, 50.0],
});
// 使用迭代器方法
let stats = gradebook.statistics();
println!("Statistics: {:?}", stats);
println!("\nTop 2 students:");
for student in gradebook.top_students(2) {
println!(" {}: {:.2}", student.name, student.average_score());
}
println!("\nFailing students (< 60):");
for student in gradebook.failing_students(60.0) {
println!(" {}: {:.2}", student.name, student.average_score());
}
println!("\nStudents aged 20:");
for student in gradebook.search_students(|s| s.age == 20) {
println!(" {}: {}", student.name, student.age);
}
println!("\nGrouped by age:");
for (age, students) in gradebook.group_by_age() {
println!(" Age {}: {} students", age, students.len());
}
}
🎯 总结要点
- 迭代器是 Rust 的核心抽象,提供了零成本的惰性序列处理
- 三种迭代器:
iter()、iter_mut()、into_iter() - 适配器链:可以组合多个适配器形成处理管道
- 消费器:最终产生结果的操作
- 自定义迭代器:实现
Iteratortrait - 性能:迭代器通常与手写循环一样快
- 并行迭代器:使用 Rayon 进行并行处理
- 错误处理:在迭代器链中合理处理错误
掌握 Rust 迭代器是编写高效、安全、表达力强的 Rust 代码的关键。迭代器的函数式风格让代码更加声明式,易于理解和维护。