Skip to content

Day 13: 集合类型

Rust标准库提供了丰富的集合类型,位于 std::collections 模块中。最常用的三种是:

  • Vec<T> - 动态数组
  • HashMap<K, V> - 键值对哈希表
  • HashSet<T> - 无序集合

这些集合类型都存储在堆上,能够动态增长,非常灵活。

Vec 是Rust中最常用的集合类型,可以存储相同类型的多个值。

fn main() {
// 创建Vec的三种方式
let mut vec1: Vec<i32> = Vec::new();
vec1.push(1);
vec1.push(2);
vec1.push(3);
let vec2 = vec![1, 2, 3]; // 使用宏创建并初始化
let mut vec3 = Vec::<i32>::with_capacity(10); // 预分配容量
vec3.push(1);
vec3.push(2);
// 访问元素
println!("vec2[0] = {}", vec2[0]);
println!("vec2.get(1) = {:?}", vec2.get(1));
// 遍历
for item in &vec2 {
println!("元素: {}", item);
}
// 常用方法
vec1.push(4); // 添加元素
let last = vec1.pop(); // 弹出最后一个元素
println!("poped: {:?}", last);
vec1.insert(1, 10); // 在指定位置插入
vec1.remove(0); // 移除指定位置元素
println!("vec1 len: {}, capacity: {}", vec1.len(), vec1.capacity());
}

HashMap 存储键值对,提供 O(1) 的查找复杂度。

use std::collections::HashMap;
fn main() {
// 创建空HashMap
let mut scores: HashMap<&str, i32> = HashMap::new();
// 插入键值对
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
// 使用 collect 创建HashMap
let teams = vec![String::from("Blue"), String::from("Yellow")];
let initial_scores = vec![10, 50];
let scores2: HashMap<_, _> = teams.into_iter().zip(initial_scores.into_iter()).collect();
// 访问值
let team_name = "Blue";
let score = scores.get(team_name).copied().unwrap_or(0);
println!("{} 队得分: {}", team_name, score);
// 更新值的三种方式
let mut map = HashMap::new();
map.insert("apple", 3);
// 1. 直接覆盖
map.insert("apple", 5);
// 2. 使用 or_insert
let entry = map.entry("orange").or_insert(10);
*entry += 5; // orange 变成 15
// 3. 使用 or_insert 获取引用
println!("苹果的数量: {}", map.get("apple").copied().unwrap_or(0));
// 遍历
for (key, value) in &map {
println!("{}: {}", key, value);
}
}

HashSet 是不存储重复值的集合,常用于去重或集合运算。

use std::collections::HashSet;
fn main() {
let a = vec![1, 2, 3, 4, 5];
let b = vec![4, 5, 6, 7, 8];
let a_set: HashSet<_> = a.into_iter().collect();
let b_set: HashSet<_> = b.into_iter().collect();
// 集合运算
println!("交集: {:?}", a_set.intersection(&b_set).collect::<Vec<_>>());
println!("并集: {:?}", a_set.union(&b_set).collect::<Vec<_>>());
println!("差集 (a-b): {:?}", a_set.difference(&b_set).collect::<Vec<_>>());
println!("对称差集: {:?}", a_set.symmetric_difference(&b_set).collect::<Vec<_>>());
// 判断包含关系
let c = HashSet::from([1, 2, 3]);
println!("c 是 a 的子集: {}", a_set.is_superset(&c));
}

Box<T> 是最简单的智能指针,用于在堆上分配数据。当你需要一个固定大小但又想占用更少空间的值时使用。

fn main() {
// 在堆上创建一个 i32 值
let b = Box::new(5);
println!("b = {}", b);
// Box 用于递归类型
// 列表类型(递归定义)
enum List {
Cons(i32, Box<List>),
Nil,
}
use List::{Cons, Nil};
let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
// Box 作为 trait 对象
trait Drawable {
fn draw(&self);
}
struct Circle {
radius: f64,
}
impl Drawable for Circle {
fn draw(&self) {
println!("绘制圆,半径: {}", self.radius);
}
}
let shapes: Vec<Box<dyn Drawable>> = vec![Box::new(Circle { radius: 5.0 })];
for shape in &shapes {
shape.draw();
}
}
use std::collections::{VecDeque, LinkedList, BinaryHeap};
use std::cmp::Ordering;
fn main() {
// VecDeque - 双端队列,适合高效的队列操作
let mut deque = VecDeque::new();
deque.push_back(1);
deque.push_front(0);
println!("Deque: {:?}", deque);
// LinkedList - 双向链表
let mut list = LinkedList::new();
list.push_back(3);
list.push_front(1);
list.push_back(4);
println!("LinkedList: {:?}", list);
// BinaryHeap - 二叉堆(最大堆)
let mut heap = BinaryHeap::new();
heap.push(3);
heap.push(1);
heap.push(4);
heap.push(1);
println!("Heap (as vec): {:?}", heap);
println!("Pop: {:?}", heap.pop());
}

今天我们学习了Rust的核心集合类型:

  • Vec:动态数组,提供 push、pop、insert 等操作
  • HashMap:键值对存储,O(1)查找,适合计数器和关联数据
  • HashSet:去重集合,提供丰富的集合运算(交、并、差)
  • Box:堆分配智能指针,用于递归类型和trait对象

明天我们将深入学习Rust的字符串类型,理解 String 与 &str 的区别和用法。