Rust集合类型与迭代器——高效处理复杂数据结构的核心工具

6 阅读25分钟

一、学习目标与重点

1.1 学习目标

  1. 掌握标准库集合类型:理解Vec、HashMap、HashSet、BTreeMap、BTreeSet的定义、常用操作、内存管理与适用场景,学会根据业务需求选择合适的集合
  2. 精通迭代器系统:熟练运用标准库迭代器的链式操作适配器(filter、map、fold等)、消费者(collect、sum等),理解其惰性求值特性
  3. 优化集合操作:深入了解不同集合的时间/空间复杂度,避免常见的性能陷阱(如Vec频繁扩容、HashMap哈希碰撞)
  4. 实现自定义迭代器:学习Iterator trait的完整实现流程,编写符合业务需求的自定义迭代器
  5. 实战集合开发:结合真实场景编写单词统计、用户数据管理、任务调度系统,解决复杂的数据处理问题

1.2 学习重点

💡 三大核心难点

  1. Vec的内存扩容策略:容量与长度的关系、预分配内存的优化技巧、插入删除操作的性能影响
  2. 迭代器的链式调用与所有权转移:如何正确处理迭代过程中元素的所有权(如into_iter、iter、iter_mut的区别)
  3. HashMap的高级API与性能优化:Entry API的使用(插入或更新、删除或获取)、负载因子的调整、哈希函数的自定义

⚠️ 三大高频错误点

  1. Vec索引越界:访问不存在的索引导致程序panic
  2. 迭代器的双重可变引用:在for循环中直接修改集合导致编译错误(违反借用规则)
  3. HashMap键类型不符合要求:键类型未同时实现Hash和Eq trait

二、[标准库]集合类型详解

Rust标准库提供了五种常用的集合类型,它们都存储在[堆内存]上,具有动态大小的特点。

2.1 动态数组 Vec

Vec是Rust中最常用的线性集合类型,类似于C++的std::vector,支持快速的随机访问和尾部插入/删除操作。

2.1.1 基本操作

⌨️ Vec基本操作示例

use std::vec::Vec;

fn main() {
    // 创建Vec的方法
    let mut vec1 = Vec::new();  // 创建空Vec
    let vec2 = vec![1, 2, 3];  // 使用vec!宏创建
    let mut vec3 = Vec::with_capacity(10);  // 预分配10个元素的容量

    // 插入元素
    vec1.push(4);
    vec1.push(5);
    vec3.extend([6, 7, 8].iter());  // 批量插入
    vec3.insert(1, 9);  // 在索引1处插入9

    // 删除元素
    vec3.pop();  // 删除尾部元素(返回Some(8))
    vec3.remove(1);  // 删除索引1处的元素(返回9)

    // 访问元素
    println!("vec2[0]: {}", vec2[0]);  // 随机访问(panic如果索引越界)
    println!("vec2.get(3): {:?}", vec2.get(3));  // 安全访问(返回None)
    let first_element = vec2.first().expect("vec2是空的");  // 获取第一个元素(Option类型)
    println!("vec2.first(): {}", first_element);

    // 修改元素
    let mut vec4 = vec![10, 20, 30];
    vec4[0] = 100;  // 直接修改
    if let Some(element) = vec4.get_mut(1) {  // 安全修改
        *element = 200;
    }
    println!("vec4: {:?}", vec4);  // [100, 200, 30]

    // 遍历Vec
    println!("vec1遍历:");
    for element in &vec1 {  // 不可变引用遍历
        println!("{}", element);
    }

    println!("vec1可变引用遍历并修改:");
    for element in &mut vec1 {  // 可变引用遍历
        *element *= 2;
        println!("{}", element);
    }

    println!("vec1消费遍历:");
    for element in vec1 {  // 消费遍历(转移所有权)
        println!("{}", element);
    }
    // println!("vec1: {:?}", vec1);  // 编译错误:vec1的所有权已转移

    // Vec的容量与长度
    let mut vec5 = Vec::with_capacity(5);
    println!("vec5初始容量: {}", vec5.capacity());  // 5
    println!("vec5初始长度: {}", vec5.len());  // 0

    for i in 0..10 {
        vec5.push(i);
        println!("插入第{}个元素后,容量: {}, 长度: {}", i + 1, vec5.capacity(), vec5.len());
    }
}

AI写代码rust
运行
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
2.1.2 高级用法

✅ 预分配内存优化:使用Vec::with_capacity预分配足够的容量,避免频繁扩容导致的内存拷贝
✅ 容量调整:使用shrink_to_fit将容量缩小到与长度相同
✅ 切片转换:使用as_slice&vec[..]将Vec转换为切片(Slice),使用from_slice将切片转换为Vec
✅ 批量操作:使用extendappendretain进行批量插入、合并、过滤操作

⌨️ Vec高级用法示例

fn main() {
    // 预分配内存优化
    let mut vec1 = Vec::with_capacity(1000);
    for i in 0..1000 {
        vec1.push(i);
    }
    println!("vec1预分配后容量: {}", vec1.capacity());  // 1000

    // 容量调整
    vec1.truncate(500);  // 截断到长度500
    println!("vec1截断后长度: {}", vec1.len());  // 500
    println!("vec1截断后容量: {}", vec1.capacity());  // 1000
    vec1.shrink_to_fit();  // 缩小容量到500
    println!("vec1缩小后容量: {}", vec1.capacity());  // 500

    // 切片转换
    let vec2 = vec![1, 2, 3];
    let slice = vec2.as_slice();
    println!("vec2转换为切片: {:?}", slice);

    let vec3 = Vec::from(slice);
    println!("切片转换为Vec: {:?}", vec3);

    // 批量操作
    let mut vec4 = vec![1, 3, 5, 7, 9];
    vec4.extend([11, 13].iter());  // 批量插入
    println!("vec4批量插入后: {:?}", vec4);

    let mut vec5 = vec![2, 4, 6];
    vec4.append(&mut vec5);  // 合并vec5到vec4(vec5变为空)
    println!("vec4合并vec5后: {:?}", vec4);
    println!("vec5合并后: {:?}", vec5);

    vec4.retain(|x| x % 2 == 1);  // 保留奇数
    println!("vec4保留奇数后: {:?}", vec4);
}

AI写代码rust
运行
123456789101112131415161718192021222324252627282930313233343536
2.1.3 适用场景与时间复杂度

✅ 适用场景:需要频繁随机访问或尾部插入/删除的场景,如列表、数组缓冲区
✅ 时间复杂度

  • 随机访问:O(1)
  • 尾部插入/删除:O(1)( amortized,平均)
  • 中间插入/删除:O(n)
  • 扩容:O(n)(当容量不足时,重新分配2倍内存并拷贝所有元素)

2.2 哈希表 HashMap<K, V>

HashMap<K, V>是Rust中最常用的键值对集合类型,类似于C++的std::unordered_map,支持快速的插入、删除、查找操作(平均O(1))。

2.2.1 基本操作

⌨️ HashMap<K, V>基本操作示例

use std::collections::HashMap;

fn main() {
    // 创建HashMap的方法
    let mut map1 = HashMap::new();  // 创建空HashMap
    let map2 = HashMap::from([
        ("key1", "value1"),
        ("key2", "value2"),
        ("key3", "value3"),
    ]);  // 使用from方法创建
    let mut map3 = HashMap::with_capacity(10);  // 预分配10个桶的容量

    // 插入元素
    map1.insert("key1", 10);
    map1.insert("key2", 20);
    map3.extend([("key3", 30), ("key4", 40)].iter());  // 批量插入

    // 删除元素
    map1.remove("key1");  // 删除键为key1的元素(返回Some(10))
    map1.clear();  // 清空所有元素

    // 访问元素
    let value1 = map2.get("key1").expect("key1不存在");  // 安全访问(返回Option类型)
    println!("map2.get("key1"): {}", value1);

    // 修改元素
    let mut map4 = HashMap::from([("name", "张三"), ("age", "25")]);
    map4.insert("age", "26");  // 直接覆盖
    if let Some(value) = map4.get_mut("name") {  // 安全修改
        *value = "李四";
    }
    println!("map4修改后: {:?}", map4);

    // 遍历HashMap
    println!("map2遍历键:");
    for key in map2.keys() {
        println!("{}", key);
    }

    println!("map2遍历值:");
    for value in map2.values() {
        println!("{}", value);
    }

    println!("map2遍历键值对:");
    for (key, value) in &map2 {  // 不可变引用遍历
        println!("{}: {}", key, value);
    }

    println!("map4遍历键值对并修改:");
    for (key, value) in map4.iter_mut() {  // 可变引用遍历
        if key == &"age" {
            *value = "27";
        }
        println!("{}: {}", key, value);
    }

    // HashMap的容量与负载因子
    let mut map5 = HashMap::with_capacity(10);
    for i in 0..8 {
        map5.insert(i, i * 2);
        println!("插入第{}个元素后,容量: {}, 长度: {}, 负载因子: {}", i + 1, map5.capacity(), map5.len(), map5.len() as f64 / map5.capacity() as f64);
    }
}

AI写代码rust
运行
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
2.2.2 高级用法:Entry API

Entry API是HashMap最强大的功能之一,它允许我们原子性地执行“插入或更新”、“删除或获取”等操作,避免了多次查找导致的性能损耗。

⌨️ Entry API示例

use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();
    scores.insert("张三", 80);

    // 插入或更新:如果键存在,就执行更新操作;如果不存在,就插入默认值
    let zhang_san_score = scores.entry("张三").or_insert(0);
    *zhang_san_score += 10;
    println!("张三的分数: {}", zhang_san_score);

    let li_si_score = scores.entry("李四").or_insert(0);
    *li_si_score += 90;
    println!("李四的分数: {}", li_si_score);

    let wang_wu_score = scores.entry("王五").or_insert_with(|| {
        println!("王五的分数不存在,插入默认值85");
        85
    });
    println!("王五的分数: {}", wang_wu_score);

    // 删除或获取:如果键存在,就获取并删除值;如果不存在,就返回默认值
    let removed_score = scores.remove_entry("张三").map(|(_, v)| v).unwrap_or(0);
    println!("删除张三的分数: {}", removed_score);

    // 批量更新:统计单词出现的次数
    let text = "Hello, Rust! This is a test. Hello, world!";
    let mut word_count = HashMap::new();

    for word in text.split_whitespace() {
        let clean_word = word.chars()
            .filter(|c| c.is_alphanumeric())
            .collect::<String>()
            .to_lowercase();

        if !clean_word.is_empty() {
            word_count.entry(clean_word).and_modify(|count| *count += 1).or_insert(1);
        }
    }

    println!("单词统计: {:?}", word_count);
}

AI写代码rust
运行
123456789101112131415161718192021222324252627282930313233343536373839404142
2.2.3 适用场景与时间复杂度

✅ 适用场景:需要频繁插入、删除、查找键值对的场景,如用户数据管理、缓存系统、单词统计
✅ 时间复杂度

  • 插入/删除/查找:平均O(1),最坏O(n)(哈希碰撞严重)
  • 遍历:O(n)

⚠️ 性能优化技巧

  1. 预分配容量:使用HashMap::with_capacity预分配足够的桶容量,避免频繁扩容
  2. 调整负载因子:默认负载因子为0.75,可以通过HashMap::with_hasherHashMap::with_capacity_and_hasher调整,但会影响空间复杂度
  3. 自定义哈希函数:使用std::collections::hash_map::DefaultHasher以外的哈希函数,如SipHash、FnvHash(需要第三方库)

2.3 哈希集合 HashSet

HashSet是Rust中最常用的集合类型,类似于C++的std::unordered_set,它存储不重复的元素,支持快速的插入、删除、查找操作(平均O(1))。

2.3.1 基本操作

⌨️ HashSet基本操作示例

use std::collections::HashSet;

fn main() {
    // 创建HashSet的方法
    let mut set1 = HashSet::new();  // 创建空HashSet
    let set2 = HashSet::from([1, 2, 3]);  // 使用from方法创建
    let mut set3 = HashSet::with_capacity(10);  // 预分配10个桶的容量

    // 插入元素
    set1.insert(4);
    set1.insert(5);
    set3.extend([6, 7, 8].iter());  // 批量插入

    // 删除元素
    set1.remove(&4);  // 删除值为4的元素(返回true)
    set1.clear();  // 清空所有元素

    // 查找元素
    let contains_2 = set2.contains(&2);  // 判断是否包含值为2的元素
    println!("set2.contains(&2): {}", contains_2);

    // 遍历HashSet
    println!("set2遍历:");
    for element in &set2 {
        println!("{}", element);
    }

    // 集合运算
    let set_a = HashSet::from([1, 2, 3, 4]);
    let set_b = HashSet::from([3, 4, 5, 6]);

    println!("set_a: {:?}", set_a);
    println!("set_b: {:?}", set_b);

    println!("交集: {:?}", set_a.intersection(&set_b).collect::<Vec<_>>());
    println!("并集: {:?}", set_a.union(&set_b).collect::<Vec<_>>());
    println!("差集: {:?}", set_a.difference(&set_b).collect::<Vec<_>>());
    println!("对称差集: {:?}", set_a.symmetric_difference(&set_b).collect::<Vec<_>>());

    // 子集判断
    let set_c = HashSet::from([3, 4]);
    let is_subset = set_c.is_subset(&set_a);
    println!("set_c是set_a的子集: {}", is_subset);
}

AI写代码rust
运行
1234567891011121314151617181920212223242526272829303132333435363738394041424344
2.3.2 适用场景与时间复杂度

✅ 适用场景:需要存储不重复元素且频繁进行集合运算的场景,如标签管理、去重操作、权限验证
✅ 时间复杂度:与HashMap<K, V>相同,因为HashSet内部是HashMap<T, ()>的封装

2.4 有序字典 BTreeMap<K, V>

BTreeMap<K, V>是Rust中最常用的有序键值对集合类型,类似于C++的std::map,它存储按键排序的键值对,支持快速的插入、删除、查找操作(O(log n))。

2.4.1 基本操作

⌨️ BTreeMap<K, V>基本操作示例

use std::collections::BTreeMap;

fn main() {
    // 创建BTreeMap的方法
    let mut map1 = BTreeMap::new();  // 创建空BTreeMap
    let map2 = BTreeMap::from([
        ("key1", "value1"),
        ("key2", "value2"),
        ("key3", "value3"),
    ]);  // 使用from方法创建

    // 插入元素
    map1.insert("key1", 10);
    map1.insert("key2", 20);

    // 删除元素
    map1.remove("key1");  // 删除键为key1的元素(返回Some(10))
    map1.clear();  // 清空所有元素

    // 访问元素
    let value1 = map2.get("key1").expect("key1不存在");  // 安全访问(返回Option类型)
    println!("map2.get("key1"): {}", value1);

    // 修改元素
    let mut map4 = BTreeMap::from([("name", "张三"), ("age", "25")]);
    map4.insert("age", "26");  // 直接覆盖
    if let Some(value) = map4.get_mut("name") {  // 安全修改
        *value = "李四";
    }
    println!("map4修改后: {:?}", map4);

    // 遍历BTreeMap
    println!("map2遍历键(有序):");
    for key in map2.keys() {
        println!("{}", key);
    }

    println!("map2遍历值(有序):");
    for value in map2.values() {
        println!("{}", value);
    }

    println!("map2遍历键值对(有序):");
    for (key, value) in &map2 {  // 不可变引用遍历
        println!("{}: {}", key, value);
    }

    // 范围查询
    let mut map5 = BTreeMap::from([(1, "a"), (2, "b"), (3, "c"), (4, "d"), (5, "e")]);
    println!("范围查询1..=3: {:?}", map5.range(1..=3).collect::<Vec<_>>());
    println!("范围查询..3: {:?}", map5.range(..3).collect::<Vec<_>>());
    println!("范围查询3..: {:?}", map5.range(3..).collect::<Vec<_>>());
}

AI写代码rust
运行
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
2.4.2 适用场景与时间复杂度

✅ 适用场景:需要存储有序键值对且频繁进行范围查询的场景,如任务调度、排行榜、数据库索引
✅ 时间复杂度

  • 插入/删除/查找:O(log n)
  • 范围查询:O(log n + k)(k是查询结果的数量)
  • 遍历:O(n)

2.5 有序集合 BTreeSet

BTreeSet是Rust中最常用的有序集合类型,类似于C++的std::set,它存储按值排序的不重复元素,支持快速的插入、删除、查找操作(O(log n))。

2.5.1 基本操作

⌨️ BTreeSet基本操作示例

use std::collections::BTreeSet;

fn main() {
    // 创建BTreeSet的方法
    let mut set1 = BTreeSet::new();  // 创建空BTreeSet
    let set2 = BTreeSet::from([1, 2, 3]);  // 使用from方法创建

    // 插入元素
    set1.insert(4);
    set1.insert(5);

    // 删除元素
    set1.remove(&4);  // 删除值为4的元素(返回true)
    set1.clear();  // 清空所有元素

    // 查找元素
    let contains_2 = set2.contains(&2);  // 判断是否包含值为2的元素
    println!("set2.contains(&2): {}", contains_2);

    // 遍历BTreeSet
    println!("set2遍历(有序):");
    for element in &set2 {
        println!("{}", element);
    }

    // 集合运算
    let set_a = BTreeSet::from([1, 2, 3, 4]);
    let set_b = BTreeSet::from([3, 4, 5, 6]);

    println!("set_a: {:?}", set_a);
    println!("set_b: {:?}", set_b);

    println!("交集: {:?}", set_a.intersection(&set_b).collect::<Vec<_>>());
    println!("并集: {:?}", set_a.union(&set_b).collect::<Vec<_>>());
    println!("差集: {:?}", set_a.difference(&set_b).collect::<Vec<_>>());
    println!("对称差集: {:?}", set_a.symmetric_difference(&set_b).collect::<Vec<_>>());

    // 范围查询
    let mut set_c = BTreeSet::from([10, 20, 30, 40, 50]);
    println!("范围查询20..=40: {:?}", set_c.range(20..=40).collect::<Vec<_>>());
    println!("范围查询..30: {:?}", set_c.range(..30).collect::<Vec<_>>());
    println!("范围查询30..: {:?}", set_c.range(30..).collect::<Vec<_>>());
}

AI写代码rust
运行
12345678910111213141516171819202122232425262728293031323334353637383940414243
2.5.2 适用场景与时间复杂度

✅ 适用场景:需要存储有序不重复元素且频繁进行范围查询的场景,如任务调度、排序去重、权限验证
✅ 时间复杂度:与BTreeMap<K, V>相同,因为BTreeSet内部是BTreeMap<T, ()>的封装

三、迭代器系统详解

迭代器系统是Rust中最强大的功能之一,它允许我们以统一的方式遍历各种集合类型,并且支持链式操作惰性求值,提高了代码的可读性和可维护性。

3.1 迭代器的定义与基本操作

迭代器是实现了Iterator trait的类型,它有一个next方法,每次调用返回一个Option<Self::Item>类型的值,当迭代结束时返回None

⌨️ 迭代器基本操作示例

use std::collections::HashMap;

fn main() {
    // Vec的迭代器
    let vec = vec![1, 2, 3];
    let mut vec_iter = vec.iter();  // 不可变引用迭代器
    println!("vec.iter().next(): {:?}", vec_iter.next());  // Some(1)
    println!("vec.iter().next(): {:?}", vec_iter.next());  // Some(2)
    println!("vec.iter().next(): {:?}", vec_iter.next());  // Some(3)
    println!("vec.iter().next(): {:?}", vec_iter.next());  // None

    let mut vec_iter_mut = vec.iter_mut();  // 可变引用迭代器
    while let Some(element) = vec_iter_mut.next() {
        *element *= 2;
    }
    println!("vec: {:?}", vec);  // [2, 4, 6]

    let mut vec_into_iter = vec.into_iter();  // 消费迭代器(转移所有权)
    while let Some(element) = vec_into_iter.next() {
        println!("{}", element);
    }
    // println!("vec: {:?}", vec);  // 编译错误:vec的所有权已转移

    // HashMap的迭代器
    let map = HashMap::from([("key1", "value1"), ("key2", "value2")]);
    let mut map_iter = map.iter();
    println!("map.iter().next(): {:?}", map_iter.next());  // Some(("key1", "value1"))

    // 范围的迭代器
    let range = 1..=5;
    let mut range_iter = range.iter();
    println!("range.iter().next(): {:?}", range_iter.next());  // Some(1)
}

AI写代码rust
运行
123456789101112131415161718192021222324252627282930313233

3.2 迭代器的适配器与消费者

迭代器系统提供了两种类型的方法

  1. 适配器(Adapter) :接受一个迭代器作为输入,返回一个新的迭代器(如filter、map、take)
  2. 消费者(Consumer) :接受一个迭代器作为输入,返回一个非迭代器类型的值(如collect、sum、fold)
3.2.1 适配器示例

⌨️ 迭代器适配器示例

fn main() {
    let vec = vec![1, 2, 3, 4, 5];

    // filter:过滤满足条件的元素
    let filtered_vec: Vec<_> = vec.iter()
        .filter(|&&x| x % 2 == 1)  // 保留奇数
        .map(|&x| x * 2)  // 乘以2
        .collect();
    println!("filtered_vec: {:?}", filtered_vec);  // [2, 6, 10]

    // take:只取前3个元素
    let taken_vec: Vec<_> = vec.iter()
        .take(3)
        .collect();
    println!("taken_vec: {:?}", taken_vec);  // [1, 2, 3]

    // skip:跳过前2个元素
    let skipped_vec: Vec<_> = vec.iter()
        .skip(2)
        .collect();
    println!("skipped_vec: {:?}", skipped_vec);  // [3, 4, 5]

    // chain:连接两个迭代器
    let vec1 = vec![1, 2];
    let vec2 = vec![3, 4];
    let chained_vec: Vec<_> = vec1.iter()
        .chain(vec2.iter())
        .collect();
    println!("chained_vec: {:?}", chained_vec);  // [1, 2, 3, 4]

    // zip:将两个迭代器合并成一个元组迭代器
    let vec3 = vec![1, 2, 3];
    let vec4 = vec!["a", "b", "c"];
    let zipped_vec: Vec<_> = vec3.iter()
        .zip(vec4.iter())
        .collect();
    println!("zipped_vec: {:?}", zipped_vec);  // [(1, "a"), (2, "b"), (3, "c")]
}

AI写代码rust
运行
1234567891011121314151617181920212223242526272829303132333435363738
3.2.2 消费者示例

⌨️ 迭代器消费者示例

fn main() {
    let vec = vec![1, 2, 3, 4, 5];

    // collect:将迭代器转换为集合类型(如Vec、HashMap、HashSet)
    let vec_collected: Vec<_> = vec.iter().collect();
    println!("vec_collected: {:?}", vec_collected);

    // sum:计算所有元素的和
    let sum = vec.iter().sum::<i32>();
    println!("sum: {}", sum);  // 15

    // product:计算所有元素的积
    let product = vec.iter().product::<i32>();
    println!("product: {}", product);  // 120

    // fold:累加器操作
    let fold_result = vec.iter().fold(0, |acc, &x| acc + x * 2);
    println!("fold_result: {}", fold_result);  // 0 + 2 + 4 + 6 + 8 + 10 = 30

    // any:判断是否有满足条件的元素
    let has_even = vec.iter().any(|&&x| x % 2 == 0);
    println!("has_even: {}", has_even);  // true

    // all:判断是否所有元素都满足条件
    let all_even = vec.iter().all(|&&x| x % 2 == 0);
    println!("all_even: {}", all_even);  // false
}

AI写代码rust
运行
123456789101112131415161718192021222324252627

3.3 惰性求值特性

Rust的迭代器是惰性求值的,也就是说,迭代器的适配器操作只有在调用消费者方法时才会真正执行。这种特性可以提高代码的性能,避免不必要的计算。

⌨️ 惰性求值示例

fn main() {
    // 这个操作不会真正执行,因为没有调用消费者方法
    let vec = vec![1, 2, 3];
    let _filtered_iter = vec.iter().filter(|&&x| {
        println!("过滤操作:{}", x);  // 不会输出
        x % 2 == 1
    });

    // 只有在调用collect方法时才会执行
    let filtered_vec: Vec<_> = vec.iter().filter(|&&x| {
        println!("过滤操作:{}", x);
        x % 2 == 1
    }).collect();
    println!("filtered_vec: {:?}", filtered_vec);
    // 输出:
    // 过滤操作:1
    // 过滤操作:2
    // 过滤操作:3
    // filtered_vec: [1, 3]
}

AI写代码rust
运行
1234567891011121314151617181920

3.4 实现自定义迭代器

我们可以通过实现Iterator trait来编写符合自己业务需求的自定义迭代器,只需要实现一个next方法即可。

⌨️ 自定义迭代器示例

// 定义一个自定义的RangeIter类型
struct RangeIter {
    current: i32,
    end: i32,
}

impl RangeIter {
    fn new(start: i32, end: i32) -> Self {
        RangeIter { current: start, end }
    }
}

// 实现Iterator trait
impl Iterator for RangeIter {
    type Item = i32;

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

// 定义一个自定义的EvenRangeIter类型,继承自RangeIter,只返回偶数
struct EvenRangeIter {
    iter: RangeIter,
}

impl EvenRangeIter {
    fn new(start: i32, end: i32) -> Self {
        EvenRangeIter { iter: RangeIter::new(start, end) }
    }
}

// 实现Iterator trait
impl Iterator for EvenRangeIter {
    type Item = i32;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(x) = self.iter.next() {
            if x % 2 == 0 {
                return Some(x);
            }
        }
        None
    }
}

fn main() {
    // 测试RangeIter
    println!("RangeIter 0..5:");
    for x in RangeIter::new(0, 5) {
        println!("{}", x);
    }

    println!("----------");

    // 测试EvenRangeIter
    println!("EvenRangeIter 0..5:");
    for x in EvenRangeIter::new(0, 5) {
        println!("{}", x);
    }

    // 使用适配器操作自定义迭代器
    let even_squared: Vec<_> = EvenRangeIter::new(0, 10)
        .map(|x| x * x)
        .collect();
    println!("EvenRangeIter 0..10平方: {:?}", even_squared);
}

AI写代码rust
运行
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273

四、真实案例应用

4.1 案例1:实现高效的单词统计系统

💡 场景分析:需要编写一个高效的单词统计系统,支持统计文本中单词出现的次数,过滤特殊字符,不区分大小写。

⌨️ 代码示例

use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

// 定义单词统计函数
fn count_words_in_file(file_path: PathBuf) -> Result<HashMap<String, u32>, Box<dyn std::error::Error>> {
    let file = File::open(file_path)?;
    let reader = BufReader::new(file);
    let mut word_count = HashMap::new();

    for line_result in reader.lines() {
        let line = line_result?;
        let cleaned_line = line.chars()
            .map(|c| if c.is_alphanumeric() || c.is_whitespace() { c } else { ' ' })
            .collect::<String>();

        for word in cleaned_line.split_whitespace() {
            let lower_word = word.to_lowercase();
            word_count.entry(lower_word).and_modify(|count| *count += 1).or_insert(1);
        }
    }

    Ok(word_count)
}

// 排序单词统计结果(按出现次数降序)
fn sort_word_count(word_count: HashMap<String, u32>) -> Vec<(String, u32)> {
    let mut sorted_word_count: Vec<_> = word_count.into_iter().collect();
    sorted_word_count.sort_by(|a, b| b.1.cmp(&a.1));
    sorted_word_count
}

fn main() {
    // 读取命令行参数
    let args: Vec<String> = std::env::args().collect();
    if args.len() != 2 {
        println!("Usage: cargo run <file_path>");
        return;
    }

    let file_path = PathBuf::from(&args[1]);

    // 统计单词
    let word_count = match count_words_in_file(file_path) {
        Ok(count) => count,
        Err(e) => {
            println!("错误: {}", e);
            return;
        }
    };

    // 排序结果
    let sorted_word_count = sort_word_count(word_count);

    // 输出结果
    println!("单词统计结果(按出现次数降序):");
    println!("----------");
    println!("{:<20} {}", "单词", "出现次数");
    println!("----------");
    for (word, count) in sorted_word_count {
        println!("{:<20} {}", word, count);
    }
}

AI写代码rust
运行
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364

4.2 案例2:实现用户数据管理系统

💡 场景分析:需要编写一个简单的用户数据管理系统,支持添加用户、删除用户、查询用户、修改用户信息,使用BTreeMap存储用户数据,以便按用户名排序。

⌨️ 代码示例

use std::collections::BTreeMap;
use std::io::{stdin, stdout, Write};

// 定义用户结构体
#[derive(Debug)]
struct User {
    name: String,
    email: String,
    age: u8,
}

impl User {
    fn new(name: String, email: String, age: u8) -> Self {
        User { name, email, age }
    }

    fn print_info(&self) {
        println!("姓名: {}", self.name);
        println!("邮箱: {}", self.email);
        println!("年龄: {}", self.age);
    }
}

// 定义用户数据管理系统
struct UserManager {
    users: BTreeMap<String, User>,
}

impl UserManager {
    fn new() -> Self {
        UserManager { users: BTreeMap::new() }
    }

    fn add_user(&mut self, user: User) {
        self.users.insert(user.name.clone(), user);
        println!("用户添加成功");
    }

    fn delete_user(&mut self, name: &str) {
        if self.users.remove(name).is_some() {
            println!("用户删除成功");
        } else {
            println!("用户不存在");
        }
    }

    fn find_user(&self, name: &str) -> Option<&User> {
        self.users.get(name)
    }

    fn modify_user(&mut self, name: &str, email: Option<String>, age: Option<u8>) {
        if let Some(user) = self.users.get_mut(name) {
            if let Some(email) = email {
                user.email = email;
            }
            if let Some(age) = age {
                user.age = age;
            }
            println!("用户信息修改成功");
        } else {
            println!("用户不存在");
        }
    }

    fn list_users(&self) {
        if self.users.is_empty() {
            println!("用户列表是空的");
            return;
        }

        println!("用户列表(按用户名排序):");
        println!("----------");
        for (_, user) in &self.users {
            user.print_info();
            println!("----------");
        }
    }
}

// 获取用户输入的辅助函数
fn get_input(prompt: &str) -> String {
    print!("{}", prompt);
    stdout().flush().expect("刷新缓冲区失败");

    let mut input = String::new();
    stdin().read_line(&mut input).expect("读取输入失败");
    input.trim().to_string()
}

fn main() {
    let mut user_manager = UserManager::new();

    loop {
        println!("用户数据管理系统");
        println!("----------------");
        println!("1. 添加用户");
        println!("2. 删除用户");
        println!("3. 查询用户");
        println!("4. 修改用户信息");
        println!("5. 列出所有用户");
        println!("6. 退出");
        println!("----------------");
        println!("请输入操作编号:");

        let choice = get_input("");

        match choice.as_str() {
            "1" => {
                println!("请输入用户信息:");
                let name = get_input("姓名:");
                let email = get_input("邮箱:");
                let age_str = get_input("年龄:");

                if let Ok(age) = age_str.parse::<u8>() {
                    let user = User::new(name, email, age);
                    user_manager.add_user(user);
                } else {
                    println!("年龄无效,请输入整数");
                }
            }
            "2" => {
                let name = get_input("请输入要删除的用户姓名:");
                user_manager.delete_user(&name);
            }
            "3" => {
                let name = get_input("请输入要查询的用户姓名:");
                if let Some(user) = user_manager.find_user(&name) {
                    println!("用户信息:");
                    user.print_info();
                } else {
                    println!("用户不存在");
                }
            }
            "4" => {
                let name = get_input("请输入要修改的用户姓名:");
                let email = get_input("请输入新的邮箱(留空表示不修改):");
                let age_str = get_input("请输入新的年龄(留空表示不修改):");

                let email = if email.is_empty() { None } else { Some(email) };
                let age = if age_str.is_empty() {
                    None
                } else {
                    age_str.parse::<u8>().ok()
                };

                user_manager.modify_user(&name, email, age);
            }
            "5" => user_manager.list_users(),
            "6" => {
                println!("用户数据管理系统结束");
                break;
            }
            _ => println!("无效的操作编号"),
        }

        println!();
    }
}

AI写代码rust
运行
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158

五、常见问题与解决方案

5.1 Vec的索引越界

问题现象:访问不存在的索引导致程序panic。

解决方案

  1. 使用getget_mut方法安全访问,返回Option类型
  2. 在访问前检查索引是否在有效范围内
  3. 使用迭代器遍历Vec,避免直接访问索引

5.2 迭代器的双重可变引用

问题现象:在for循环中直接修改集合导致编译错误(违反借用规则)。

解决方案

  1. 使用iter_mut方法获取可变引用迭代器
  2. 如果需要在遍历过程中删除元素,可以使用retain方法
  3. 如果需要在遍历过程中插入元素,可以使用Vec::insert方法,但会影响性能(O(n)时间复杂度)

5.3 HashMap的键类型不符合要求

问题现象:键类型未同时实现Hash和Eq trait。

解决方案

  1. 检查键类型是否实现了Hash和Eq trait
  2. 如果使用自定义类型作为键,需要手动实现Hash和Eq trait
  3. 可以使用derive宏自动实现Hash和Eq trait(如#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)])

六、总结与展望

6.1 总结

✅ 掌握了标准库集合类型:理解了Vec、HashMap、HashSet、BTreeMap、BTreeSet的定义、常用操作、适用场景与时间复杂度
✅ 精通了迭代器系统:熟练运用了标准库迭代器的链式操作、适配器、消费者,理解了其惰性求值特性
✅ 优化了集合操作:学习了Vec的预分配内存优化、HashMap的Entry API与性能优化技巧
✅ 实现了自定义迭代器:深入学习了Iterator trait的完整实现流程,编写了符合自己业务需求的自定义迭代器
✅ 实战集合开发:结合真实场景编写了两个实用的代码案例:高效的单词统计系统和用户数据管理系统

6.2 展望

下一篇文章,我们将深入学习Rust的文件操作与网络编程,包括文件的读写、目录的操作、网络通信(TCP、UDP、HTTP),通过这些知识我们将能够编写更复杂的应用程序,如Web服务器、客户端、数据处理工具。