Rust入门失败之Iterator Basic

Iterator

  • Iterator实现了std::iter::Iteratortrait, 包含next等方法.

    1
    2
    3
    4
    5
    trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
    ... // many default methods
    }
  • iteriter_mut两个方法生成每个Item的sharedmutable reference, 这两个方法是大多数容器提供的方法, 而非Iterator方法.

IntoIterator

  • iterable是指实现了std::iter::IntoIteratortrait的值, 包含into_iter方法, 也是for循环调用的方法.

    1
    2
    3
    4
    5
    trait IntoIterator where Self::IntoIter::Item == Self::Item {
    type Item;
    type IntoIter: Iterator;
    fn into_iter(self) -> Self::IntoIter;
    }
  • 很多容器也实现了IntoIteratortrait, 但是根据自身不同的场景, 有不同的实现:

    • 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
      10
      use 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
    3
    for 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
      10
      use 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
      7
      use 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");