🎬 HoRain云小助手个人主页

 🔥 个人专栏: 《Linux 系列教程》《c语言教程

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

专栏介绍

专栏名称

专栏介绍

《C语言》

本专栏主要撰写C干货内容和编程技巧,让大家从底层了解C,把更多的知识由抽象到简单通俗易懂。

《网络协议》

本专栏主要是注重从底层来给大家一步步剖析网络协议的奥秘,一起解密网络协议在运行中协议的基本运行机制!

《docker容器精解篇》

全面深入解析 docker 容器,从基础到进阶,涵盖原理、操作、实践案例,助您精通 docker。

《linux系列》

本专栏主要撰写Linux干货内容,从基础到进阶,知识由抽象到简单通俗易懂,帮你从新手小白到扫地僧。

《python 系列》

本专栏着重撰写Python相关的干货内容与编程技巧,助力大家从底层去认识Python,将更多复杂的知识由抽象转化为简单易懂的内容。

《试题库》

本专栏主要是发布一些考试和练习题库(涵盖软考、HCIE、HRCE、CCNA等)

目录

⛳️ 推荐

专栏介绍

📊 一、核心概念与特性

🔧 二、创建迭代器

1. 基于集合创建

2. 其他创建方式

⚙️ 三、迭代器适配器 (Iterator Adaptors)

🍽️ 四、消费者 (Consumers)

💡 五、实现自定义迭代器

🚀 六、进阶技巧与性能

📝 七、实用示例


img

Rust 的迭代器是其处理数据序列的核心抽象,它通过 Iterator trait 和 IntoIterator trait 提供了强大、高效且安全的数据遍历和操作能力。下面我将为你梳理 Rust 迭代器的核心概念、使用方法以及最佳实践。

📊 一、核心概念与特性

Rust 的迭代器遵循​​惰性求值​​原则,即只有在真正消费数据时才会执行计算,这避免了不必要的性能开销。

​特性​ ​说明​
​惰性求值​ 创建迭代器适配器(如 map)不会立即执行,只有在调用​​消费者​​方法(如 collect)时才会进行计算。
​零成本抽象​ 迭代器编译后通常被优化为与手动编写循环相当的机器码,几乎无额外开销。
​所有权与借用​ 通过 iter()(不可变借用)、iter_mut()(可变借用)、into_iter()(获取所有权)三种方式适配不同场景。

🔧 二、创建迭代器

1. 基于集合创建

最常用的方式是从集合类型(如 Vec、数组)创建迭代器。

​方法​ ​产出元素类型​ ​所有权情况​ ​原集合后续可用性​
iter() &T 不可变借用
iter_mut() &mut T 可变借用
into_iter() T 获取所有权(转移)
let vec = vec!["a", "b", "c"];
let iter_ref = vec.iter();      // 产生 &str, vec 仍可用
let iter_mut = vec.iter_mut();  // 产生 &mut str, vec 仍可用
let iter_owned = vec.into_iter(); // 产生 String, vec 被消耗,后续不可用
2. 其他创建方式
  • ​范围表达式​​:(1..5) 生成 1 到 4 的整数,(1..=5) 生成 1 到 5 的整数。
  • ​函数生成​​:std::iter::from_fn 接受一个返回 Option<T> 的函数来生成迭代器。std::iter::successors 基于前一个值生成下一个值。

⚙️ 三、迭代器适配器 (Iterator Adaptors)

适配器对现有迭代器进行转换,返回一个新的迭代器。由于惰性求值,调用适配器​​本身不会立即触发计算​​。

​适配器​ ​作用​ ​示例​
map 对每个元素应用闭包进行转换 `vec![1, 2, 3].iter().map(
filter 只保留满足条件的元素 `vec![1, 2, 3].iter().filter(
filter_map 同时进行过滤和映射,闭包返回 Option<T>None 被丢弃 `vec!["1", "a", "2"].iter().filter_map(
flat_map 对每个元素应用返回迭代器的闭包,并将结果扁平化 `vec!["hello", "world"].iter().flat_map(
flatten 将嵌套的迭代器结构(如 Iterator<Item=Iterator>)扁平化为一层 vec![vec![1, 2], vec![3]].iter().flatten() → 1, 2, 3
take 取前 n 个元素 (1..).take(3) → 1, 2, 3
take_while 一直取元素,直到条件第一次为 false `vec![1, 2, 3, 4].iter().take_while(
skip 跳过前 n 个元素 vec![1, 2, 3].iter().skip(2) → 3
skip_while 一直跳过元素,直到条件第一次为 false `vec![1, 2, 3, 4].iter().skip_while(
zip 将两个迭代器“拉链”在一起,产生元组 vec!["a", "b"].iter().zip(vec![1, 2].iter()) → ("a", 1), ("b", 2)
chain 连接两个迭代器 vec![1, 2].iter().chain(vec![3].iter()) → 1, 2, 3
enumerate 产生 (索引, 元素) 对 vec!['a', 'b'].iter().enumerate() → (0, 'a'), (1, 'b')
fuse 使迭代器在第一次返回 None 后永远返回 None,避免后续调用 next 的行为不确定性

🍽️ 四、消费者 (Consumers)

消费者会消耗迭代器,触发计算并产生最终结果(如集合、值等)。

​消费者​ ​作用​ ​示例​ ​返回类型​
collect 将迭代器收集到集合中 vec![1, 2].iter().collect::<Vec<_>>()Vec<&i32> 集合类型
sum 对元素求和 vec![1, 2].iter().sum() → 3 数值类型
product 对元素求积 vec![2, 3].iter().product() → 6 数值类型
fold 从初始值开始,通过闭包累积计算 vec![1,2].iter().fold(0, |acc, x| acc + x) → 3 任意类型
count 统计元素数量 vec![1, 2].iter().count() → 2 usize
last 取最后一个元素 vec![1, 2].iter().last()Some(&2) Option<Item>
nth 取第 n 个元素(从 0 开始) vec![1, 2].iter().nth(1)Some(&2) Option<Item>
find 查找第一个满足条件的元素 vec![1,2].iter().find(|x| **x == 1)Some(&1) Option<Item>
any 判断是否有任意元素满足条件 vec![1,2].iter().any(|x| **x == 3)false bool
all 判断是否所有元素都满足条件 vec![1,2].iter().all(|x| *x > 0)true bool
for_each 对每个元素执行闭包(类似于循环) vec![1,2].iter().for_each(|x| println!("{}", x)) → 打印 1, 2 ()
partition 根据条件将元素分区到两个不同的集合中 vec![1,2].iter().partition(|x| *x % 2 == 0) → (vec![2], vec![1]) (Vec, Vec)

💡 五、实现自定义迭代器

你可以为自己的类型实现 Iterator trait 来创建自定义迭代器。

// 一个简单的计数器迭代器
struct Counter {
    current: u32,
    max: u32,
}

impl Iterator for Counter {
    type Item = u32; // 指定迭代器产生的元素类型

    fn next(&mut self) -> Option<Self::Item> {
        if self.current < self.max {
            let val = self.current;
            self.current += 1;
            Some(val)
        } else {
            None
        }
    }
}

// 使用自定义迭代器
let counter = Counter { current: 0, max: 3 };
let nums: Vec<_> = counter.collect(); // [0, 1, 2]

🚀 六、进阶技巧与性能

  1. for 循环与迭代器​​:Rust 的 for 循环本质上是迭代器的语法糖。for item in collection { ... } 等价于 let mut iter = collection.into_iter(); while let Some(item) = iter.next() { ... }
  2. ​性能​​:迭代器是​​零成本抽象​​,编译器会高度优化迭代器代码,其性能通常与手动编写的循环相当,有时甚至更优。
  3. ​短路求值​​:take_whileanyallfind 等方法会在条件满足时提前终止迭代,提升效率。

📝 七、实用示例

// 处理日志数据:解析、过滤、统计
#[derive(Debug)]
struct LogEntry {
    ip: String,
    status_code: u16,
    bytes: usize,
}

fn process_logs(lines: Vec<&str>) -> (Vec<LogEntry>, f64) {
    // 使用 filter_map 同时进行解析和过滤(无效行返回 None 被丢弃)
    let entries: Vec<LogEntry> = lines
        .into_iter()
        .filter_map(|line| {
            let parts: Vec<&str> = line.split_whitespace().collect();
            if parts.len() >= 3 {
                Some(LogEntry {
                    ip: parts[0].to_string(),
                    status_code: parts[2].parse().unwrap_or(0),
                    bytes: parts.get(3).and_then(|s| s.parse().ok()).unwrap_or(0),
                })
            } else {
                None
            }
        })
        .collect();

    // 计算成功请求的比例 (状态码 2xx 或 3xx 视为成功)
    let total = entries.len();
    let success_count = entries.iter().filter(|e| e.status_code >= 200 && e.status_code < 400).count();
    let success_ratio = if total > 0 { success_count as f64 / total as f64 } else { 0.0 };

    (entries, success_ratio)
}

希望这份详细的梳理能帮助你全面掌握 Rust 迭代器的强大功能!

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐