Iterator
Iterator实现了
std::iter::Iterator
trait, 包含next
等方法.1
2
3
4
5trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
... // many default methods
}iter
和iter_mut
两个方法生成每个Item的shared或mutable reference, 这两个方法是大多数容器提供的方法, 而非Iterator方法.
IntoIterator
*
iterable
*是指实现了std::iter::IntoIterator
trait的值, 包含into_iter
方法, 也是for
循环调用的方法.1
2
3
4
5trait IntoIterator where Self::IntoIter::Item == Self::Item {
type Item;
type IntoIter: Iterator;
fn into_iter(self) -> Self::IntoIter;
}很多容器也实现了
IntoIterator
trait, 但是根据自身不同的场景, 有不同的实现:shared reference
的collection,into_iter()
返回的是items的shared reference
.*
mutable reference
*的collection同理.按值传递的collection(passed collection by value)会取得collection的所有权,
into_iter()
返回的也是取出Item’s ownership的iterator. 当这个iterator销毁时, 整个collection也销毁.1
2
3
4
5
6
7
8
9
10use std::collections::BTreeSet;
let mut favorites = BTreeSet::new();
favorite.insert("Game of Thrones".to_string());
favorite.insert("Breaking Bad".to_string());
let mut it = favorites.into_iter(); // Take ownership of favorites
assert_eq!(it.next(), Some("Game of Thrones".to_string()));
assert_eq!(it.next(), "Breaking Bad".to_string());
assert_eq!(it.next(), None); // favorites now empty.对应的三种
for
循环如下:
1
2
3for element in &collection {...}
for element in &mut collection {...}
for element in collection {...}并不是所有的容器都实现了这三种:
像
HashMap
,BTreeMap
这类容器返回的是value的mutable reference, key的shared reference. 因为key的hash值不能变.而
HashSet
,BTreeSet
这类没有实现返回*mutable reference,*同样因为它的值对容器有特殊意义, 不能变.Slices
没有实现第三种by value, 因为它并不拥有item的所有权.当对
IntoIterator
返回的iterator有类型要求时(例如for循环), 可以用IntoIterator<Item=xxx>
泛型来指定:1
2
3
4
5
6
7
8
9
10use std::fmt::Debug;
fn dump<T, U>(t: T)
where T: IntoIterator<Item=U>,
U: Debug
{
for u in t {
println!("{:?}", u);
}
}大部分容器提供一个
drain
方法, 该方法不属于IntoIterator, 它和IntoIterator的into_iter
方法不同的是它不会消费collection的所有权, 而是获取collection的一个mutable reference, 并返回一个获取每个元素所有权(passes ownership of each element to the consumer)的iterator.1
2
3
4
5
6
7use std::iter::FromIterator;
let mut outer = "Earth".to_string();
let inner = String::from_iter(outer.drain(1..4));
assert_eq!(outer, "Eh");
assert_eq!(inner, "art");