rust语言学习笔记Trait(七) IntoIterator(由集合创建迭代器)

IntoIterator 是 Rust 迭代器的‌入口 trait 。它的核心职责是将一个类型(如集合、数组等)转换为一个实现了 Iterator trait 的迭代器对象。

  • 任何实现了 IntoIterator 的类型都可以直接在 for 循环中使用‌。

1、核心定义

rust 复制代码
pub trait IntoIterator {
    /// 迭代器产生的元素类型
    type Item;
    
    /// 具体的迭代器类型,必须实现 Iterator<Item = Self::Item>
    type IntoIter: Iterator<Item = Self::Item>;
    
    /// 消耗 self,创建并返回迭代器
    fn into_iter(self) -> Self::IntoIter;
}
  • **Item**‌: 定义迭代过程中产生的每个元素的类型。
  • ‌**IntoIter**‌: 定义实际执行迭代逻辑的类型。
  • ‌**into_iter(self)**‌: 这是转换的核心。注意它接收 self(按值传递),这意味着调用该方法通常会消耗原始数据的所有权(或者借用,取决于具体实现)。

2、三种迭代模式的所有权

(1)消费所有权 (impl IntoIterator for Vec<T>)

for item in vecvec.into_iter()
rust 复制代码
let v1 = vec![1, 2, 3, 4];
for i in v1 {                  // 消费所有权
    println!("{}", i);
}
println!("{:?}", v1);          // ❌已被移动


let v2 = vec![1, 2, 3, 4];
for i in v2.into_iter() {      // 消费所有权
    println!("{}", i);
}
println!("{:?}", v2);          // ❌已被移动

(2)不可变借用 (impl<'a, T> IntoIterator for &'a Vec<T>)

for item in &vec(&vec).into_iter()
rust 复制代码
let v1 = vec![1, 2, 3, 4];
for i in &v1 {                   // 不可变借用
    println!("{}", i);
}
println!("{:?}", v1);            // ✅正常输出


let v2 = vec![1, 2, 3, 4];
for i in (&v2).into_iter() {     // 不可变借用
    println!("{}", i);
}
println!("{:?}", v2);            // ✅正常输出

(3)可变借用 (impl<'a, T> IntoIterator for &'a mut Vec<T>)

for item in &mut vec(&mut vec).into_iter()
rust 复制代码
let mut v1 = vec![1, 2, 3, 4];
for i in &mut v1 {                  // 可变借用
    *i += 2;
}
println!("{:?}", v1);               // 已被修改


let mut v2 = vec![1, 2, 3, 4];
for i in (&mut v2).into_iter() {    // 可变借用
    *i -= 2;
}
println!("{:?}", v2);                // 已被修改

3、函数参数约束 IntoIterator

  • 函数参数必须满足:任何可迭代内容
rust 复制代码
use std::fmt::{Debug, Display};

fn my_fn<I, T>(v: I)
where
    I: IntoIterator<Item=T>,   // 参数必须实现了 IntoIterator
    T: Display,                // 用于 print 输出
{
    for i in v {               // 遍历迭代器
        print!("{}  ", i);
    }
    println!("");
}

fn main() {
    my_fn(vec![1, 2, 3]);             // Vec<i32>
    my_fn([1, 2, 3, 4]);              // &[i32]
    my_fn((5..9));                    // range(i32)
    my_fn(["aaa", "bbb", "ccc"]);     // &[&str]
}

4、自定义类型实现 IntoIterator

rust 复制代码
#[derive(Debug)]
struct MyList<T>(Vec<T>);              // 自定义集合

// 实现消费所有权的 IntoIterator
impl<T> IntoIterator for MyList<T> {
    type Item = T;
    type IntoIter = std::vec::IntoIter<T>;
    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

// 实现不可变引用借用的 IntoIterator
impl<'a, T> IntoIterator for &'a MyList<T> {
    type Item = &'a T;
    type IntoIter = std::slice::Iter<'a, T>;
    fn into_iter(self) -> Self::IntoIter {
        self.0.iter()
    }
}

// 实现可变引用借用的 IntoIterator
impl<'a, T> IntoIterator for &'a mut MyList<T> {
    type Item = &'a mut T;
    type IntoIter = std::slice::IterMut<'a, T>;
    fn into_iter(self) -> Self::IntoIter {
        self.0.iter_mut()
    }
}

fn main() {
    // 消费所有权
    let list1 = MyList(vec![1, 2, 3]);
    for item in list1 {
        println!("{}", item);
    }

    // 不可变借用
    let list2 = MyList(vec![4, 5, 6]);
    for item in &list2 {
        println!("{}", item);
    }

    // 可变借用
    let mut list3 = MyList(vec![4, 5, 6]);
    for item in &mut list3 {
        *item += 10;
    }
    println!("{:?}", list3);
}
相关推荐
独孤留白9 小时前
从C到Rust:Rust 的 Trait 不是Interface,那是什么?
rust
花褪残红青杏小17 小时前
Rust图像处理第7节-马赛克像素化:分块取平均色实现打码风格
rust·webassembly·图形学
doiito1 天前
【Agent Harness】Gliding Horse 设计细节 -- 不跟风开发自己的AI Agent
架构·rust·agent
doiito1 天前
【Agent Harness】Gliding Horse 核心设计理念,不跟风开发自己的AI Agent
ai·rust·架构设计·系统设计·ai agent
花褪残红青杏小2 天前
Rust图像处理第6节- 均值模糊 & 中值模糊:3×3 邻域的两种经典玩法
rust·webassembly·图形学
子兮曰2 天前
前端工具链的「Rust 化」:一场没有赢家的军备竞赛?
前端·后端·rust
星栈2 天前
写 Dioxus Demo 不难,难的是把它写成项目
前端·rust·前端框架
mCell2 天前
【锐评】桌面端技术营销:别拿跑分当工程判断
前端·rust·electron
武子康2 天前
调查研究-201 Rust 里的 dev build 和 release build:为什么同一份代码性能差这么多?
后端·架构·rust
RainCity2 天前
Java Swing 自定义组件库分享(十二)
java·笔记·后端