程序中,迭代器负责遍历每一个项。Rust的迭代器是惰性的,仅当调用迭代器的方法时才生效。
介绍
- Rust 中所有的迭代器都实现了
iterator trait
,其中 iterator trait
定义在标准库,定义如下:
pub trait Iterator {
type Item;
fn next(&mut self) -> Option(Self::Item);
// ...
}
说明:
- 实现
Iterator trait
需要定义一个 Item 类型,它用于 next 方法的返回类型 Iterator trait
需要实现 next 方法,next 方法如下:- 每次调用返回迭代器中的一项
- 返回结果放在 Some 里
- 迭代器结束,返回 None
- 可以直接在迭代器上调用 next 方法
- 消耗迭代器的方法:标准库中,
Iterator trait
有一些带默认实现的方法,一些会调用 next,即为消耗性迭代器- 如:
let x = vec![1, 2, 3]; let total:i32 = x.iter().sum();
- 迭代器适配器:把迭代器转换为不同类型的迭代方法
- Rust 中迭代器通过
零开销抽象(Zero-Cost Abstraction)
在抽象时不会引起额外的运行时开销
示例
fn main() {
let x = vec![1, 2, 3];
let mut x_iter = x.iter(); // next 时改变当前位置
// for i in x_iter {
// println!("{}", i);
// }
assert_eq!(x_iter.next(), Some(&1));
assert_eq!(x_iter.next(), Some(&2));
let x: Vec<i32> = vec![1, 2, 3];
let y: Vec<_> = x.iter().map(|x| x+1).collect();
println!("x: {:?}, y:{:?}", x, y); // x: [1, 2, 3], y:[2, 3, 4]
}
说明:
map
方法接收一个闭包,对所有值加一,并产生一个新的迭代器collect
方法是消耗性迭代器,把结果收集到一个集合类型中- 上述示例采用了链式调用,可读性高
几种迭代方法
iter
:在不可变引用上创建迭代器into_iter
:创建的迭代器会获得所有权iter_mut
:迭代可变的引用
使用闭包捕获环境
filter()
迭代器
- 接收一个闭包:遍历迭代器的每一个元素,返回 bool 类型
- true:当前元素会包含在 filter 产生的迭代器中
- false:当前元素不会包含在 filter 产生的迭代器中
自定义迭代器
使用 Iterator trait
创建自定义迭代器需要实现 next
方法
struct Counter {
count: u32,
}
impl Counter {
fn new() -> Counter {
Counter { count: 0 }
}
}
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
self.count += 1;
Some(self.count)
}
}
#[test]
fn test_counter() {
let mut c = Counter::new();
assert_eq!(c.next(), Some(1));
assert_eq!(c.next(), Some(2));
assert_eq!(c.next(), Some(3));
}