Rust进阶[part8]_迭代器

Rust进阶[part8]_迭代器
SoniaChenRust进阶[part8]_迭代器&关联类型
概述
迭代器(Iterator)是 Rust 中处理序列元素的强大工具,它提供了一种统一的方式来遍历集合(如向量、数组、哈希表等)中的元素。迭代器的核心特性是惰性执行:除非主动调用消耗迭代器的方法,否则迭代器不会实际执行任何操作。这种特性使得迭代器可以高效地组合使用,而不会带来额外的性能开销。
在 Rust 中,迭代器由 Iterator
trait 定义,所有实现了该 trait 的类型都可以被称为迭代器。迭代器不仅可以用于遍历现有集合,还可以用于生成序列(如斐波那契数列)、处理数据流等场景。
迭代器的实现
迭代器本质是实现了 Iterator
trait 的类型。该 trait 的核心定义如下:
trait Iterator {
type Item; // 关联类型:迭代器产生的元素类型
fn next(&mut self) -> Option<Self::Item>; // 核心方法:返回下一个元素(None表示结束)
}
next
方法是迭代器的核心:
- 每次调用返回
Option<Self::Item>
,其中Some(value)
表示下一个元素,None
表示迭代结束 - 调用
next
会修改迭代器的内部状态(推进到下一个元素),因此需要&mut self
关联类型
上面 trait 中用到的 type Item;
是关联类型(Associated Type),它是在 trait 内部定义的类型占位符,用于表示 trait 中涉及的某个类型。实现该 trait 时,需要指定 Item
的具体类型。
和泛型的区别
关联类型与泛型都可以实现"类型抽象",但适用场景不同:
-
关联类型:在 trait 中只声明一个类型占位符,实现 trait 时必须为该类型指定唯一具体类型(一个实现对应一个具体类型)。适合 trait 中某个类型逻辑上"固定"的场景(如迭代器的元素类型)。
// 迭代器只能产生一种类型的元素,用关联类型更合适 trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; }
-
泛型:在 trait 定义时声明类型参数,实现 trait 时可以为不同类型参数提供多个实现。适合需要为多种类型提供通用逻辑的场景。
// 泛型可以为不同T实现不同逻辑 trait Container<T> { fn get(&self, index: usize) -> Option<&T>; }
简单迭代器
迭代器的基本使用示例:
fn iter_study() {
let v1 = vec![1, 2, 3];
// 1. for循环遍历(最常用)
let v1_iter = v1.iter(); // 获取迭代器(不可变引用)
for var in v1_iter {
println!("{}", var); // 输出:1 2 3
}
// 2. 手动调用next方法
let mut v1_iter2 = v1.iter(); // 需要mut,因为next会修改迭代器状态
while let Some(var) = v1_iter2.next() {
println!("{}", var); // 输出:1 2 3
}
}
for 循环不需要 mut 而 while 循环需要的原因:
for 循环在内部会自动处理迭代器的可变性——它会将迭代器标记为 mutable,并在循环过程中隐式调用 next
方法。而手动调用 next
时,需要显式声明 mut
,因为 next
方法接收 &mut self
,要求迭代器是可变的。
几个迭代的方法
集合类型(如 Vec
)通常提供以下方法来获取不同类型的迭代器:
iter 方法
返回不可变引用迭代器(Iterator<Item = &T>
),迭代过程中借用集合元素(不获取所有权),集合本身可以在迭代后继续使用。
let v = vec![1, 2, 3];
let iter = v.iter(); // 迭代元素类型:&i32
into_iter 方法
返回所有权迭代器(Iterator<Item = T>
),迭代过程中会获取集合元素的所有权,迭代结束后集合本身无法再使用(已被消耗)。
let v = vec![1, 2, 3];
let iter = v.into_iter(); // 迭代元素类型:i32(v此后不可用)
iter_mut 方法
返回可变引用迭代器(Iterator<Item = &mut T>
),迭代过程中可以修改集合元素的值。
let mut v = vec![1, 2, 3];
let iter = v.iter_mut(); // 迭代元素类型:&mut i32
for num in iter {
*num *= 2; // 修改元素值
}
println!("{:?}", v); // 输出:[2, 4, 6]
消耗迭代器的方法
消耗型方法(Consuming Adaptors)会遍历迭代器并消耗它(调用后迭代器无法再使用),通常会产生一个最终结果。
next
最基础的消耗型方法,每次调用返回下一个元素,直到返回 None
。
sum
计算迭代器中所有元素的总和,支持所有实现了 Sum
trait 的类型(如数值类型)。
let v = vec![1, 2, 3, 4];
let total: i32 = v.iter().sum(); // sum会消耗迭代器
println!("{}", total); // 输出:10
collect
将迭代器产生的元素收集到一个集合中(如 Vec
、HashMap
等),需要显式指定目标集合类型。
let v = vec![1, 2, 3];
let doubled: Vec<i32> = v.iter().map(|x| x * 2).collect(); // 收集到Vec
println!("{:?}", doubled); // 输出:[2, 4, 6]
产生其他迭代器的方法
迭代器适配器(Iterator Adaptors)会对迭代器进行转换,产生一个新的迭代器(不立即执行,仍保持惰性)。
map
接收一个闭包作为参数,将迭代器中的每个元素转换为另一种类型,返回一个新的迭代器。
let v = vec![1, 2, 3];
let mapped = v.iter().map(|x| x * 10); // 类型:Map<Iter<i32>, ...>(未执行)
// 用collect触发执行
let result: Vec<i32> = mapped.collect();
println!("{:?}", result); // 输出:[10, 20, 30]
filter
接收一个闭包作为 predicate(断言),该闭包返回 bool
,新迭代器只包含满足断言的元素。
let v = vec![1, 2, 3, 4, 5];
let even_numbers: Vec<&i32> = v.iter().filter(|x| **x % 2 == 0).collect();
println!("{:?}", even_numbers); // 输出:[2, 4]
练习:实现斐波那契数列迭代器
题目描述
实现一个自定义迭代器,用于生成斐波那契数列。该迭代器应支持无限生成斐波那契数,直到用户停止迭代。
任务要求
- 实现结构体
Fibonacci
,并为它实现Iterator
trait。 - 在
next
方法中生成下一个斐波那契数。 - 编写测试函数,输出前10个斐波那契数。
实现代码
use std::iter::Iterator;
// 定义斐波那契迭代器结构体,存储当前和下一个斐波那契数
struct Fibonacci {
current: u64,
next: u64,
}
// 为Fibonacci实现Iterator trait
impl Iterator for Fibonacci {
type Item = u64; // 迭代器产生u64类型的斐波那契数
fn next(&mut self) -> Option<Self::Item> {
let current_val = self.current; // 保存当前值作为返回结果
// 更新下一组值(斐波那契规则:下一个数 = 当前数 + 前一个数)
let new_next = self.current + self.next;
self.current = self.next;
self.next = new_next;
Some(current_val) // 始终返回Some(无限迭代)
}
}
// 提供一个构造函数,初始化斐波那契迭代器(从0, 1开始)
impl Fibonacci {
fn new() -> Self {
Fibonacci { current: 0, next: 1 }
}
}
// 测试函数:输出前10个斐波那契数
fn test_fibonacci() {
let fib_iter = Fibonacci::new();
// take(10)限制只取前10个元素(迭代器适配器)
for (i, num) in fib_iter.t ake(10).enumerate() {
println!("第{}个斐波那契数:{}", i + 1, num);
}
}
// 运行测试
fn main() {
test_fibonacci();
}
输出结果
第1个斐波那契数:0
第2个斐波那契数:1
第3个斐波那契数:1
第4个斐波那契数:2
第5个斐波那契数:3
第6个斐波那契数:5
第7个斐波那契数:8
第8个斐波那契数:13
第9个斐波那契数:21
第10个斐波那契数:34
说明
- 结构体
Fibonacci
用current
和next
存储当前和下一个斐波那契数,初始化为0
和1
(符合斐波那契数列的数学定义)。 next
方法通过更新current
和next
的值生成下一个数,始终返回Some
(实现无限迭代)。- 使用
take(10)
适配器限制只获取前10个元素,避免无限循环。