Rust 集合类型与迭代器:高效处理复杂数据结构
Rust 集合类型与迭代器涵盖了 Vec、HashMap、HashSet、BTreeMap、BTreeSet 的定义与操作,重点解析迭代器的链式调用、适配器与消费者机制及惰性求值特性。文章包含 Vec 内存扩容策略、HashMap Entry API 优化技巧、自定义迭代器实现流程,并结合单词统计与用户管理系统案例,提供复杂数据结构处理的实战方案。

Rust 集合类型与迭代器涵盖了 Vec、HashMap、HashSet、BTreeMap、BTreeSet 的定义与操作,重点解析迭代器的链式调用、适配器与消费者机制及惰性求值特性。文章包含 Vec 内存扩容策略、HashMap Entry API 优化技巧、自定义迭代器实现流程,并结合单词统计与用户管理系统案例,提供复杂数据结构处理的实战方案。

【三大核心难点】
【三大高频错误点】
Rust 标准库提供了五种常用的集合类型,它们都存储在堆内存上,具有动态大小的特点。
Vec 是 Rust 中最常用的线性集合类型,类似于 C++ 的 std::vector,支持快速的随机访问和尾部插入/删除操作。
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());
}
}
Vec::with_capacity 预分配足够的容量,避免频繁扩容导致的内存拷贝shrink_to_fit 将容量缩小到与长度相同as_slice 或 &vec[..] 将 Vec 转换为切片(Slice),使用 from_slice 将切片转换为 Vecextend、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);
}
HashMap<K, V> 是 Rust 中最常用的键值对集合类型,类似于 C++ 的 std::unordered_map,支持快速的插入、删除、查找操作(平均 O(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);
}
}
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);
}
性能优化技巧:
HashMap::with_capacity 预分配足够的桶容量,避免频繁扩容HashMap::with_hasher 或 HashMap::with_capacity_and_hasher 调整,但会影响空间复杂度std::collections::hash_map::DefaultHasher 以外的哈希函数,如 SipHash、FnvHash(需要第三方库)HashSet 是 Rust 中最常用的集合类型,类似于 C++ 的 std::unordered_set,它存储不重复的元素,支持快速的插入、删除、查找操作(平均 O(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);
}
BTreeMap<K, V> 是 Rust 中最常用的有序键值对集合类型,类似于 C++ 的 std::map,它存储按键排序的键值对,支持快速的插入、删除、查找操作(O(log n))。
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<_>>());
}
BTreeSet 是 Rust 中最常用的有序集合类型,类似于 C++ 的 std::set,它存储按值排序的不重复元素,支持快速的插入、删除、查找操作(O(log n))。
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<_>>());
}
迭代器系统是 Rust 中最强大的功能之一,它允许我们以统一的方式遍历各种集合类型,并且支持链式操作和惰性求值,提高了代码的可读性和可维护性。
迭代器是实现了 Iterator trait 的类型,它有一个 next 方法,每次调用返回一个 OptionSelf::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)
}
迭代器系统提供了两种类型的方法:
迭代器适配器示例:
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")]
}
迭代器消费者示例:
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); // [1, 2, 3, 4, 5]
// 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
}
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]
}
我们可以通过实现 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);
}
场景分析:需要编写一个高效的单词统计系统,支持统计文本中单词出现的次数,过滤特殊字符,不区分大小写。
代码示例:
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);
}
}
场景分析:需要编写一个简单的用户数据管理系统,支持添加用户、删除用户、查询用户、修改用户信息,使用 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!();
}
}
问题现象:访问不存在的索引导致程序 panic。
解决方案:
get 或 get_mut 方法安全访问,返回 Option 类型问题现象:在 for 循环中直接修改集合导致编译错误(违反借用规则)。
解决方案:
iter_mut 方法获取可变引用迭代器retain 方法Vec::insert 方法,但会影响性能(O(n) 时间复杂度)问题现象:键类型未同时实现 Hash 和 Eq trait。
解决方案:
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)])下一篇文章,我们将深入学习 Rust 的文件操作与网络编程,包括文件的读写、目录的操作、网络通信(TCP、UDP、HTTP),通过这些知识我们将能够编写更复杂的应用程序,如 Web 服务器、客户端、数据处理工具。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online