Rust迭代器
Rust语言内置了迭代器模式,用于实现对一个项的序列进行特定的处理,通常配合for循环使用。当我们使用for...in
遍历一个容器向量时,其实就是在使用迭代器:
let vec = vec![1, 2, 3];
for val in vec {
println!("{} ", val);
}
为了方便开发者的使用,for...in
表达式隐藏了很多迭代器的使用和实现细节,这些我们将在后面慢慢看到。
Rust迭代器的实现
Rust迭代器的实现基于两个关键的特型:Iterator
和IntoIterator
,在Rust中,迭代器指的是任何实现std::iter::Iterator特型的值,而IntoIterator用于生成某种类型的迭代器。
Iterator特型
Rust标准库中Iterator特型定义如下:
trait Iterator {
type Item; // 产生值的类型
fn next(&mut self) -> Option<Self::Item>; // 迭代器
... //其它迭代器方法
}
Item是迭代器产生值的类型。next方法返回Option枚举值,当值为Some(v)时,v存储迭代器的下一个值;值为None时,表示序列终止。
IntoIterator特型
如果某种类型是可迭代的,那么它可以实现std::iter::IntoIterator特型。IntoIterator提供into_iter方法用于接收一个值,然后基于这个值返回一个迭代器。Rust标准库中IntoIterator特型定义如下:
trait IntoIterator where Self::IntoIter::Item == Self::Item {
type Item; // 产生值的类型
type IntoIter: Iterator; // 迭代器的类型
fn into_iter(self) -> Self::IntoIter; // 返回一个迭代器
}
IntoIter是迭代器自身的类型,Item是迭代器产生值的类型。接下来,我们再来看for循环。
for循环与迭代器
for循环的语法形式如下:
for loop_variable in collection {
code()
}
这里,变量collections就是实现了Iterator和IntoIterator的类型。Rust在后台会对上述代码进行扩展,因此,for循环的实际执行代码如下:
{
let mut _iter = std::iter::IntoIterator::into_iter(collections);
loop {
match _iter.next() {
Some(loop_variable) => {
code()
},
None => break,
}
}
}
可以看到,for循环的本质就是使用into_iterator()
方法将一些集合类型转换为迭代器,再使用next()
方法逐个遍历序列。
迭代器类型
Rust中大多数集合类型提供了不止一个IntoIterator的实现,可用来产生迭代项不可变引用、可变引用或者值类型的迭代器,对应方法和描述如下表:
方法 | 描述 | 等价形式 |
---|---|---|
into_iter() | 返回一个只读不可重入迭代器,迭代器元素的类型为 T | v.into_iter() |
iter() | 返回一个只读可重入迭代器,迭代器元素的类型为 &T | (&v).into_iter() |
iter_mut() | 返回一个可修改可重入迭代器,迭代器元素的类型为 &mut T | (&mut v).into_iter() |
其中,要说明的是iter
和iter_mut
并不是属于某种特型的方法,它们是这些集合类型额外提供的方法,可以理解为是一种简化版的使用形式。
再看for循环
由于for循环会对其操作数应用into_iterator()
方法,因此这三个实现就可以消费集合并取得其元素的所有权,以及支持迭代集合的不可变引用、可变引用:
for element in collection {} 等效于 for element in collection.into_iter() {} // 执行后,collection所有权会被转移,无法再访问
for element in &collection {} 等效于 for element in collection.iter() {}
for element in &mut collection {} 等效于 for element in collection.iter_mut() {}
实现自定义迭代器
Rust中实现自定义迭代器本质上就是为自定义类型实现Iterator和IntoIterator特型。
方式一
struct Counter {
max: i32,
// `count` tracks the state of this iterator.
count: i32,
}
impl Counter {
fn new(max: i32) -> Counter {
Counter { count: -1, max: max }
}
}
impl Iterator for Counter {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
self.count += 1;
if self.count < self.max {
Some(self.count)
} else {
None
}
}
}
// 使用for循环遍历迭代器使用
for i in Counter::new(10) {
println!("{}", i);
}
方式二
struct Counter {
max: i32,
// No need to track the state, because this isn't an iterator.
}
impl Counter {
fn new(max: i32) -> Counter {
Counter { max: max }
}
}
impl IntoIterator for Counter {
type Item = i32;
type IntoIter = std::ops::Range<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
std::ops::Range{ start: 0, end: self.max }
}
}
for i in Counter::new(10) {
println!("{}", i);
}
相关参考
- 《Rust程序设计》
- 《Rust程序设计语言》
- Rust 迭代器 Iterator:https://www.twle.cn/c/yufei/rust/rust-basic-iterator.html