概念
迭代器用来遍历序列中的每一项,它也决定了什么时候结束迭代。
迭代器是惰性的,因此迭代器的使用分为两步:创建和消费
示例:
let v1 = vec![1, 2, 3];// 获取迭代器let v1_iter = v1.iter();// 使用for循环消费迭代器for val in v1_iter {println!("Got: {}", val);}
迭代器实现了Iterator这一**trait**,trait的定义如下:
pub trait Iterator {// 定义一个关联类型type Item;// 定义next的实现fn next(&mut self) -> Option<Self::Item>;// 此处省略了方法的默认实现}
实现了Iterator trait的struct就可以成为一个迭代器
获取迭代器
获取迭代器的方式
v.iter()v.iter_mut()v.into_iter()

内部元素的类型
以Vector<**T**>来说:
- 获取引用
**&T**v.iter()(&v).into_iter()
- 获取可变引用
**&mut T**v.iter_mut()(&mut v).into_iter()
- 获取所有权
**T**v.into_iter()
下面显式调用三种获取迭代器的方法, 可以观察获取到的元素类型
for 循环自动调用 into_iter()
在为v使用for循环时,会为v自动调用into_iter()方法获取迭代器,因此可以在v前加&、& mut或直接v,以此获取变量的引用、可变引用、所有权
示例:
let mut vec = vec!(1,2,3);// 值被移动// 自动调用 v.into_iter()for x in v {println!("x = {}", x);}-----------------------------// 自动调用 (&v).into_iter()for x in &v {println!("x = {}", x);}// 等价于for x in v.iter() {println!("x = {}", x);}------------------------------// 自动调用 (&mut v).into_iter()for x in &mut v {println!("x = {}", x);}// 等价于for x in v.iter_mut() {println!("x = {}", x);}
为自定义类型实现 into_iter()
struct CountdownIterator(i32);impl Iterator for CountdownIterator {type Item = i32;fn next(&mut self) -> Option<Self::Item> {self.0 -= 1;if self.0 < 0 {None} else {Some(self.0)}}}struct Countdown(i32);impl IntoIterator for Countdown {type Item = i32;type IntoIter = CountdownIterator;fn into_iter(self) -> Self::IntoIter {CountdownIterator(self.0)}}impl<'a> IntoIterator for &'a Countdown {type Item = i32;type IntoIter = CountdownIterator;fn into_iter(self) -> Self::IntoIter {CountdownIterator(self.0)}}impl<'a> IntoIterator for &'a mut Countdown {type Item = i32;type IntoIter = CountdownIterator;fn into_iter(self) -> Self::IntoIter {CountdownIterator(self.0)}}fn main() {let c = Countdown(10);for i in &c {for j in &c {println!("({0}, {1})", i, j)}}}
Vector的迭代器实现
iter()、iter_mut()方法
是结构体的自有方法
定义:
pub fn iter(&self) -> Iter<'_, T> {Iter::new(self)}pub fn iter_mut(&mut self) -> IterMut<'_, T> {IterMut::new(self)}
**Iter**来自Struct std::slice::Iter**IterMut**来自Struct std::slice::IterMut
即Vector使用了**slice**中定义的迭代器
into_iter()方法
实现了**IntoIterato trait**中的**into_iter()**方法
定义:
pub trait IntoIterator {type Item;type IntoIter: Iterator;fn into_iter(self) -> Self::IntoIter;}
有三个实现:
// 获取借用impl<'a, T, A> IntoIterator for &'a mut Vec<T, A> whereA: Allocator,// 获取可变借用impl<'a, T, A> IntoIterator for &'a Vec<T, A> whereA: Allocator,// 获取所有权impl<T, A> IntoIterator for Vec<T, A>
消费适配器(consuming adaptors)
Iterator trait中存在一些有默认实现的其他方法,它们的实现中调用了next()方法(也就是对迭代器进行消费),这些方法被称为消费适配器(consuming adaptors)
使用sum消费适配器的示例:
fn iterator_sum() {let v1 = vec![1, 2, 3];let v1_iter = v1.into_iter();// 调用sum会获取v1_iter的所有权,因此后面不可再使用v1_iterlet sum: i32 = v1_iter.sum();assert_eq!(sum, 6);}
迭代器适配器(iterator adaptors)
Iterator trait中还有一类迭代器适配器(iterator adaptors)方法,这些方法将前一个迭代器转换为另一个迭代器,因此迭代器适配器可以链式调用。
示例:
fn iterator_adaptors() {let v1 = vec![1, 2, 3, 4];// 调用map对迭代器进行转换// collect方法属于env::args,用于消费迭代器返回一个新vectorlet v1_new_vec: Vec<i32> = v1.iter().map(|x| x + 2).collect();assert_eq!(v1_new_vec, vec![3, 4, 5, 6]);}
综合使用:自定义迭代器实现
描述:
- 创建迭代器的结构体定义
- 为结构体实现
**new**函数,返回结构体实例 - 为结构体实现
**Iterator trait**,重写**next**方法 - 测试
- 调用
**zip**方法。返回一个由2-元组组成的新迭代器,元组中的两个元素分别来自两个迭代器,下面示例的zip方法中:- 第一个迭代器中为
1,2,3,4,5 - 第二个迭代器中为
2,3,4,5 - 结果为
(1,2),(2,3),(3,4),(4,5),第五对值:(5,None)实际上从未产生过
- 第一个迭代器中为
- 调用
map方法后,结果为2,6,12,20 - 调用
filter方法后,结果为6,12 - 计算
sum后,结果为18
- 调用
示例:
// 迭代器定义struct CounterIterator {count: u32,}impl CounterIterator {fn new() -> CounterIterator {CounterIterator { count: 0 }}}// 实现Iterator trait并重写next方法的实现impl Iterator for CounterIterator {type Item = u32;fn next(&mut self) -> Option<Self::Item> {self.count += 1;if self.count < 6 {Some(self.count)} else {None}}}#[test]fn coustom_iterator_trait() {let iter = CounterIterator::new();// 连续调用迭代器消费器let sum: u32 = iter.zip(CounterIterator::new().skip(1)).map(|(a, b)| a * b).filter(|x| x % 3 == 0).sum();assert_eq!(sum, 18);}
迭代器的可变引用
消耗迭代器所有权
如果在迭代器上调用参数为**self**的消费器, 例如下面的take方法, 这个迭代器会被消耗, 之后无法使用fn [take](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.take)(**self**, n: [usize](https://doc.rust-lang.org/std/primitive.usize.html)) -> [Take](https://doc.rust-lang.org/std/iter/struct.Take.html)<Self> take方法拿走原迭代器的前**n**个元素, 返回新迭代器
这里的返回值Take是迭代器类型, 也就说调用take方法返回了一个新的迭代器: 
获取迭代器的可变引用
所以可以先拿到迭代器的可变引用, 这样的话即使调用参数为**self**的消费器, 效果也相当于**&mut self**
这个方法是fn [by_ref](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.by_ref)(&mut self) -> [&mut](https://doc.rust-lang.org/std/primitive.reference.html)Self by_ref方法借用一个迭代器, 而不是消费它
可变引用也实现了迭代器
原因是有个一揽子泛型实现: 它为迭代器的可变引用实现了Iterator trait:
可以看到里面有两次解引用操作, 以next为例, 它要获取参数的可变引用&mut self, 而此时的self类型是已经是可变引用类型&mut I, 所以next拿到的类型是**&mut &mut self**, 所以需要两次解引用操作, 经过take方法也是一样, 因为take直接返回的类型就是参数类型
