Rust 中IntoIterator和Iterator是2个密切相关但用途不同的trait,顾名思义IntoIterator用于从某个类型创建Iterator.
Trait | 作用 | 用法 | 示例 |
---|---|---|---|
Iterator | 定义了迭代器的行为,如何获取下一个元素 | .next() | vec.iter() |
IntoIterator | 从一个类型获取迭代器,定义了可以变成迭代器的类型 | .into_iter() | for x in vec |
pub trait IntoIterator {
type Item;
type IntoIter: Iterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter;
}
由定义可看到,into_iter是将原始类型的所有权转移给创建的迭代器,所以into_iter调用完成后原始变量将无法再使用。
当用for循环迭代元素时,rust 插入语法糖简化用户写法。
// ------------语法糖-----------
let v = vec![1,2,3];
for x in v{ .....}
// ------------ 等价于 -----------
for x in v.into_iter{ ......}
// ------------或者等价于 -----------
for x in IntoIterator::into_iter(v){ ........ }
同时 Rust 标准库中提供了一个blanket实现,为任何实现Iterator的类型自动实现IntoIterator trait.
但这个实现的适用范围有限,主要适用于迭代器本身,而非容器类型。
impl<I: Iterator> IntoIterator for I {
type Item = I::Item;
type IntoIter = I;
#[inline]
fn into_iter(self) -> I {
self
}
}
示例
定义一个容器类型:MyCollection,一个对应的迭代器类型:MyCollectionIter
struct MyCollection {
items: Vec<String>,
}
struct MyCollectionIter {
index: usize,
items: Vec<String>,
}
impl MyCollectionIter{
fn new(v: MyCollection) -> Self{
MyCollectionIter{
index: 0,
items: v.items,
}
}
}
为迭代器类型(MyCollectionIter)实现next方法
impl Iterator for MyCollectionIter {
type Item = String;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.items.len() {
let item = self.items[self.index].clone();
self.index += 1;
Some(item)
} else {
None
}
}
}
为容器类型实现IntoIterator,即如何从容器类型(MyCollection)生成它对应的迭代器类型(MyCollectionIter)
impl IntoIterator for MyCollection {
type Item = String;
type IntoIter = MyCollectionIter;
fn into_iter(self) -> Self::IntoIter {
MyCollectionIter::new(self)
}
}
调用示例与非语法糖的手动实现
// ------------ 语法糖 for-----------
fn main() {
let collection = MyCollection {
items: vec!["one".to_string(), "two".to_string(), "three".to_string()],
};
for item in collection {
println!("Item: {}", item);
}
}
// ------------ 手动实现 -----------
fn main() {
let collection = MyCollection {
items: vec!["one".to_string(), "two".to_string(), "three".to_string()],
};
let iter = collection.into_iter();
while let Some(item) in iter.next() {
println!("Item: {}", item);
}
}
大多数情况下实现自定义Iterator时仅需要实现next方法,Iterator剩余的其他方法标准库提供默认blanket实现;
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
....
剩余的trait内方法已提供默认实现,通常情况下不用覆盖这些实现
}
自定义类型的实现示例参见上面类型定义:MyCollectionIter
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有