【Rust自学】13.5. 迭代器 Pt.1:迭代器的定义、iterator trait和next方法

13.5.0. 写在正文之前

Rust语言在设计过程中收到了很多语言的启发,而函数式编程对Rust产生了非常显著的影响。函数式编程通常包括通过将函数作为值传递给参数、从其他函数返回它们、将它们分配给变量以供以后执行等等。

在本章中,我们会讨论 Rust 的一些特性,这些特性与许多语言中通常称为函数式的特性相似:

  • 闭包
  • 迭代器(本文)
  • 使用闭包和迭代器改进I/O项目
  • 闭包和迭代器的性能

喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=^・ω・^=)

13.5.1. 什么是迭代器

提到迭代器,就得先讲迭代器模式。迭代器模式允许你依次对一系列项里的每一个元素执行某些任务。 而在这个过程中,迭代器负责:

  • 遍历每个项
  • 确定序列(的遍历)何时完成

Rust的迭代器是懒惰的(lazy):除非调用消费迭代器的方法,否则迭代器本身没有任何效果。这句话的意思大致是如果你在代码里写了迭代器但没有用到,那么迭代器就相当于什么都没干。

看个例子:

rust 复制代码
fn main() {
	let v1 = vec![1, 2, 3];
	let v1_iter = v1.iter();
}

v1是一个Vectorv1.iter()就是在给v1产生了一个迭代器,赋给了v1_iter,但是目前v1_iter没有被使用,所以迭代器可以被看作没有任何效果。

那我们使用迭代器来遍历:

rust 复制代码
fn main() {
	let v1 = vec![1, 2, 3];
	let v1_iter = v1.iter();
	for val in v1_iter {
		println!("Got: {}", val);
	}
}

这就相当于迭代器里的每个元素都被用在了一次循环里。

13.5.2. Iterator trait

所有的迭代器都实现了Iterator trait。这个trait定义在标准库之下,定义大致如下:

rust 复制代码
pub trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;

    // methods with default implementations elided
}

这里面涉及两个新语法:type itemSelf::Item,这两个语法定义了与这个trait关联的类型,这部分放在以后的文章讲。现在你需要知道的就是实现Iterator trait需要你定义一个Item类型,它用于next方法的返回类型(迭代器的返回类型)。

iterator这个trait仅要求实现一个方法------nextnext方法每次调用迭代器它都会返回迭代器中的一项,也就是迭代器中的一个元素,而由于返回类型是Option,所以返回的结果会被包裹在Option下的Some变体里。如果迭代结束,就会返回Option下的None

实际使用时可以直接在迭代器上调用next方法,看个例子:

rust 复制代码
#[cfg(test)]
mod tests {
    #[test]
    fn iterator_demonstration() {
        let v1 = vec![1, 2, 3];

        let mut v1_iter = v1.iter();

        assert_eq!(v1_iter.next(), Some(&1));
        assert_eq!(v1_iter.next(), Some(&2));
        assert_eq!(v1_iter.next(), Some(&3));
        assert_eq!(v1_iter.next(), None);
    }
}
  • v1是一个Vectorv1_iterv1的迭代器,由于下面的操作会被视为修改迭代器内容所以得加mut关键字声明为可用。
  • assert_eq!(v1_iter.next(), Some(&1));这句话是第一次调用next,就会返回Vector里第一个元素,用Some包裹,也就是Some(&1),这里是&1是因为迭代器的返回值是被Option类型包裹的不可变引用。
  • assert_eq!(v1_iter.next(), Some(&2));是第二次调用next,就会返回Vector里第二个元素,用Some包裹,也就是Some(&2)
  • 以此类推...
  • 在迭代器上调用next方法会更改迭代器用于跟踪其在序列中位置的内部状态 。换句话说,每一次调用就是消耗了这个迭代器里一个元素。而13.5.1中例子的for循环不需要mut是因为for循环实际上取得了v1_iter的所有权。

13.5.3. 几种迭代方法

刚才使用的 iter方法生成的是一个不可变引用的迭代器 ,通过next方法所取得的值实际上是指向Vector中的元素的不可变引用。

into_iter方法创建的迭代器会获得所有权。也就是它在迭代元素时会把元素移动到新的作用域内,并取得所有权。

iter_mut方法在遍历函数时使用的是可变的引用

相关推荐
青木川崎2 分钟前
Mybatis面试题
java·开发语言·mybatis
wclass-zhengge9 分钟前
02UML图(D1_结构图)
java·开发语言·算法
老猿讲编程16 分钟前
详解Rust 中 String 和 str 的用途与区别
开发语言·后端·rust
菜鸟阿康学习编程23 分钟前
JDBC 实战项目(增删改查小系统,接近完美!)017
java·开发语言·数据库
Q_274378510927 分钟前
springboot基于微信小程序的智慧小区管理系统
spring boot·后端·微信小程序
九离十1 小时前
基于C语言的通讯录实现
c语言·开发语言
007php0071 小时前
深入了解计算机网络中的路由协议与性能优化
java·开发语言·数据库·后端·python·计算机网络·golang
brrdg_sefg1 小时前
飞牛os使用ddns-go配合华为云实现内网穿透
开发语言·golang·华为云
秋野酱1 小时前
基于javaweb的SpringBoot景区旅游管理系统设计和实现(源码+文档+部署讲解)
spring boot·后端·旅游
落霞与孤鹭齐飞。。1 小时前
SSM旅游信息管理系统
java·开发语言·mysql·毕业设计·课程设计·旅游