一、学习目标与重点
1.1 学习目标
- 掌握标准库集合类型:理解Vec、HashMap、HashSet、BTreeMap、BTreeSet的定义、常用操作、内存管理与适用场景,学会根据业务需求选择合适的集合
- 精通迭代器系统:熟练运用标准库迭代器的链式操作、适配器(filter、map、fold等)、消费者(collect、sum等),理解其惰性求值特性
- 优化集合操作:深入了解不同集合的时间/空间复杂度,避免常见的性能陷阱(如Vec频繁扩容、HashMap哈希碰撞)
- 实现自定义迭代器:学习Iterator trait的完整实现流程,编写符合业务需求的自定义迭代器
- 实战集合开发:结合真实场景编写单词统计、用户数据管理、任务调度系统,解决复杂的数据处理问题
1.2 学习重点
💡 三大核心难点:
- Vec的内存扩容策略:容量与长度的关系、预分配内存的优化技巧、插入删除操作的性能影响
- 迭代器的链式调用与所有权转移:如何正确处理迭代过程中元素的所有权(如into_iter、iter、iter_mut的区别)
- HashMap的高级API与性能优化:Entry API的使用(插入或更新、删除或获取)、负载因子的调整、哈希函数的自定义
⚠️ 三大高频错误点:
- Vec索引越界:访问不存在的索引导致程序panic
- 迭代器的双重可变引用:在for循环中直接修改集合导致编译错误(违反借用规则)
- 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
✅ 批量操作:使用extend、append、retain进行批量插入、合并、过滤操作
⌨️ 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)
⚠️ 性能优化技巧:
- 预分配容量:使用
HashMap::with_capacity预分配足够的桶容量,避免频繁扩容 - 调整负载因子:默认负载因子为0.75,可以通过
HashMap::with_hasher或HashMap::with_capacity_and_hasher调整,但会影响空间复杂度 - 自定义哈希函数:使用
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 迭代器的适配器与消费者
迭代器系统提供了两种类型的方法:
- 适配器(Adapter) :接受一个迭代器作为输入,返回一个新的迭代器(如filter、map、take)
- 消费者(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。
解决方案:
- 使用
get或get_mut方法安全访问,返回Option类型 - 在访问前检查索引是否在有效范围内
- 使用迭代器遍历Vec,避免直接访问索引
5.2 迭代器的双重可变引用
问题现象:在for循环中直接修改集合导致编译错误(违反借用规则)。
解决方案:
- 使用
iter_mut方法获取可变引用迭代器 - 如果需要在遍历过程中删除元素,可以使用
retain方法 - 如果需要在遍历过程中插入元素,可以使用
Vec::insert方法,但会影响性能(O(n)时间复杂度)
5.3 HashMap的键类型不符合要求
问题现象:键类型未同时实现Hash和Eq trait。
解决方案:
- 检查键类型是否实现了Hash和Eq trait
- 如果使用自定义类型作为键,需要手动实现Hash和Eq trait
- 可以使用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服务器、客户端、数据处理工具。