
这里写目录标题
- [一、Rust 容器(集合)详解](#一、Rust 容器(集合)详解)
-
- 1、引言
- [2、 为什么 Rust 的容器与众不同](#2、 为什么 Rust 的容器与众不同)
-
- [2.1、 所有权与容器](#2.1、 所有权与容器)
- [2.2、 泛型与零成本抽象](#2.2、 泛型与零成本抽象)
- [2.3、 性能可预测性](#2.3、 性能可预测性)
- 3、Vec:动态数组
-
- [3.1 、创建与初始化](#3.1 、创建与初始化)
- [3.2、 增删元素](#3.2、 增删元素)
- [3.3、 访问元素](#3.3、 访问元素)
- [3.4 、内存布局与容量](#3.4 、内存布局与容量)
- [3.5 、常用方法速查](#3.5 、常用方法速查)
- [4、 HashMap:哈希映射](#4、 HashMap:哈希映射)
-
- [4.1、 创建与基本操作](#4.1、 创建与基本操作)
- [4.2 、键的更新策略](#4.2 、键的更新策略)
- [4.3、 所有权规则](#4.3、 所有权规则)
- [4.4、 自定义类型作为键](#4.4、 自定义类型作为键)
- [4.5 、性能特性](#4.5 、性能特性)
- [5、 HashSet:哈希集合](#5、 HashSet:哈希集合)
-
- [5.1、 基本用法](#5.1、 基本用法)
- [5.2、 集合运算](#5.2、 集合运算)
- [5.3、 去重应用](#5.3、 去重应用)
- [6、 BTreeMap 与 BTreeSet:有序容器](#6、 BTreeMap 与 BTreeSet:有序容器)
-
- [6.1、 BTreeMap](#6.1、 BTreeMap)
- [6.2、 BTreeSet](#6.2、 BTreeSet)
- [6.3 、哈希容器 vs 有序容器](#6.3 、哈希容器 vs 有序容器)
- [7、 其他常用容器](#7、 其他常用容器)
-
- [7.1、 VecDeque:双端队列](#7.1、 VecDeque:双端队列)
- [7.2、 LinkedList:双向链表](#7.2、 LinkedList:双向链表)
- [7.3 、BinaryHeap:二叉堆](#7.3 、BinaryHeap:二叉堆)
- [8、 容器选择决策指南](#8、 容器选择决策指南)
-
- [8.1、 快速选择表](#8.1、 快速选择表)
- 9、性能优化与最佳实践
-
- [9.1、 预分配容量](#9.1、 预分配容量)
- [9.2、 避免不必要的克隆](#9.2、 避免不必要的克隆)
- [9.3 使用 entry API 避免重复查找](#9.3 使用 entry API 避免重复查找)
- [9.4 、迭代器与容器结合](#9.4 、迭代器与容器结合)
- [10、 总结](#10、 总结)
- 二、代码示例

一、Rust 容器(集合)详解
1、引言
Rust 的标准库提供了一系列强大的容器(集合)类型,用于组织和存储数据。与许多语言不同,Rust 的集合类型在设计上充分考虑了内存安全、所有权(Ownership)和借用(Borrowing)机制,这使得它们在提供高性能的同时,也能在编译期就杜绝大量内存错误。
本文将系统性地介绍 Rust 中最常用的容器类型,包括动态数组 Vec、哈希映射 HashMap、哈希集合 HashSet,以及有序集合 BTreeMap 和 BTreeSet。我们会从基本用法出发,逐步深入到内存布局、性能特性和最佳实践,帮助你根据实际场景选择最合适的容器。
2、 为什么 Rust 的容器与众不同
在深入具体类型之前,有必要先理解 Rust 容器设计的底层逻辑。Rust 的容器并非简单的"数据袋子",它们与语言的核心特性深度绑定。
2.1、 所有权与容器
Rust 的每个值都有且仅有一个所有者。当你将一个值放入容器时,实际上是将该值的所有权转移给了容器。这意味着:
- 容器负责其内部元素的析构(Drop),在容器被释放时,所有元素也会被自动清理。
- 你无法同时通过容器和外部变量持有同一份数据的可变引用,这从编译期避免了悬垂指针和数据竞争。
rust
let mut v = Vec::new();
let s = String::from("hello");
v.push(s); // s 的所有权移入 v
// println!("{}", s); // 编译错误:s 已被移动
println!("{}", v[0]); // 正确:通过容器访问
2.2、 泛型与零成本抽象
所有标准容器都是泛型类型,这意味着它们可以存储任意类型的元素,且不会引入运行时开销。编译器会在编译期根据具体类型进行单态化(Monomorphization),生成针对该类型的专用代码。
2.3、 性能可预测性
Rust 容器的时间复杂度是明确且可预测的。例如,Vec 的索引访问是 O(1),HashMap 的平均查找是 O(1),BTreeMap 的查找是 O(log n)。这种确定性使得 Rust 非常适合对性能敏感的系统编程。
3、Vec:动态数组
Vec<T> 是 Rust 中最基础、最常用的容器,它提供了一个可增长的、连续内存的数组。
3.1 、创建与初始化
rust
// 方式一:空 Vec
let mut v1: Vec<i32> = Vec::new();
// 方式二:使用宏
let mut v2 = vec![1, 2, 3];
// 方式三:指定长度和默认值
let v3 = vec![0; 5]; // [0, 0, 0, 0, 0]
// 方式四:从迭代器收集
let v4: Vec<i32> = (0..10).collect();
3.2、 增删元素
rust
let mut v = vec![1, 2, 3];
// 追加
v.push(4); // [1, 2, 3, 4]
v.insert(0, 0); // [0, 1, 2, 3, 4]
// 删除
let last = v.pop(); // Some(4),v 变为 [0, 1, 2, 3]
let first = v.remove(0); // 0,v 变为 [1, 2, 3]
// 清空
v.clear(); // []
3.3、 访问元素
rust
let v = vec![10, 20, 30];
// 索引访问(越界会 panic)
let a = v[0];
// 安全的 get 方法(返回 Option)
if let Some(b) = v.get(1) {
println!("b = {}", b);
}
// 迭代
for item in &v {
println!("{}", item);
}
// 可变迭代
let mut v2 = vec![1, 2, 3];
for item in &mut v2 {
*item *= 2;
}
3.4 、内存布局与容量
Vec 由三个部分组成:指向堆内存的指针、当前长度(len)和当前容量(capacity)。当长度达到容量时,Vec 会重新分配更大的内存并复制(或移动)原有元素。
rust
let mut v = Vec::with_capacity(10); // 预分配容量,避免频繁扩容
println!("len: {}, capacity: {}", v.len(), v.capacity());
v.push(1);
v.push(2);
println!("len: {}, capacity: {}", v.len(), v.capacity()); // 2, 10
// 收缩容量到刚好容纳当前元素
v.shrink_to_fit();
println!("len: {}, capacity: {}", v.len(), v.capacity()); // 2, 2
性能建议 :如果预先知道元素数量,使用 Vec::with_capacity 可以避免多次扩容带来的性能损耗。
3.5 、常用方法速查
| 方法 | 说明 | 时间复杂度 |
|---|---|---|
push |
末尾追加 | 均摊 O(1) |
pop |
末尾弹出 | O(1) |
insert |
指定位置插入 | O(n) |
remove |
指定位置删除 | O(n) |
contains |
是否包含某元素 | O(n) |
sort |
原地排序 | O(n log n) |
dedup |
去重(需先排序) | O(n) |
retain |
按条件保留元素 | O(n) |
4、 HashMap:哈希映射
HashMap<K, V> 存储键值对,通过哈希函数实现快速查找。它是 Rust 中最常用的关联容器。
4.1、 创建与基本操作
rust
use std::collections::HashMap;
// 创建
let mut scores = HashMap::new();
// 插入
scores.insert(String::from("Alice"), 90);
scores.insert(String::from("Bob"), 85);
// 读取
let alice_score = scores.get("Alice"); // Option<&i32>
println!("{:?}", alice_score); // Some(90)
// 遍历
for (name, score) in &scores {
println!("{}: {}", name, score);
}
4.2 、键的更新策略
rust
use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert(String::from("Alice"), 90);
// 直接覆盖
scores.insert(String::from("Alice"), 95);
// 仅在键不存在时插入
scores.entry(String::from("Bob")).or_insert(80);
// 根据旧值更新
let counter = scores.entry(String::from("Alice")).or_insert(0);
*counter += 1;
4.3、 所有权规则
rust
use std::collections::HashMap;
let mut map = HashMap::new();
let key = String::from("key");
map.insert(key, 42); // key 的所有权移入 map
// println!("{}", key); // 编译错误:key 已被移动
// 使用引用作为键(需注意生命周期)
let text = String::from("hello");
let mut ref_map: HashMap<&str, i32> = HashMap::new();
ref_map.insert(&text, 1); // 借用 text
println!("{}", text); // 仍然可用
4.4、 自定义类型作为键
作为 HashMap 的键,类型必须实现 Hash 和 Eq trait。标准库中的基本类型和 String 都已实现,自定义类型需要手动实现或使用 #[derive]:
rust
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
#[derive(Hash, Eq, PartialEq, Debug)]
struct Point {
x: i32,
y: i32,
}
let mut map = HashMap::new();
map.insert(Point { x: 1, y: 2 }, "origin");
println!("{:?}", map.get(&Point { x: 1, y: 2 }));
4.5 、性能特性
HashMap 使用 SipHash 作为默认哈希算法,这提供了良好的抗碰撞能力,但速度略慢于一些简单哈希。如果对性能有极致要求,可以使用 FxHashMap(来自 rustc-hash crate)或 ahash 等替代实现。
| 操作 | 平均时间复杂度 | 最坏情况 |
|---|---|---|
| 插入 | O(1) | O(n) |
| 查找 | O(1) | O(n) |
| 删除 | O(1) | O(n) |
5、 HashSet:哈希集合
HashSet<T> 是基于 HashMap 实现的集合,只存储键不存储值,用于快速判断元素是否存在。
5.1、 基本用法
rust
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert("apple");
set.insert("banana");
set.insert("orange");
// 判断存在
println!("{}", set.contains("apple")); // true
// 删除
set.remove("banana");
// 长度
println!("{}", set.len()); // 2
5.2、 集合运算
HashSet 支持标准的集合运算,非常适合去重、交集、并集等场景:
rust
use std::collections::HashSet;
let a: HashSet<_> = [1, 2, 3, 4].iter().cloned().collect();
let b: HashSet<_> = [3, 4, 5, 6].iter().cloned().collect();
// 并集
let union: HashSet<_> = a.union(&b).cloned().collect();
println!("{:?}", union); // {1, 2, 3, 4, 5, 6}
// 交集
let intersection: HashSet<_> = a.intersection(&b).cloned().collect();
println!("{:?}", intersection); // {3, 4}
// 差集(a 中有而 b 中没有)
let difference: HashSet<_> = a.difference(&b).cloned().collect();
println!("{:?}", difference); // {1, 2}
// 对称差集
let sym_diff: HashSet<_> = a.symmetric_difference(&b).cloned().collect();
println!("{:?}", sym_diff); // {1, 2, 5, 6}
5.3、 去重应用
rust
let nums = vec![1, 2, 2, 3, 3, 3, 4];
let unique: HashSet<_> = nums.into_iter().collect();
println!("{:?}", unique); // {1, 2, 3, 4}
6、 BTreeMap 与 BTreeSet:有序容器
当需要按键的顺序遍历数据时,BTreeMap 和 BTreeSet 是比哈希容器更合适的选择。
6.1、 BTreeMap
rust
use std::collections::BTreeMap;
let mut map = BTreeMap::new();
map.insert("c", 3);
map.insert("a", 1);
map.insert("b", 2);
// 按键排序遍历
for (key, value) in &map {
println!("{}: {}", key, value);
}
// 输出:a: 1, b: 2, c: 3
// 范围查询
let range: Vec<_> = map.range("a".."c").collect();
println!("{:?}", range); // [("a", &1), ("b", &2)]
6.2、 BTreeSet
rust
use std::collections::BTreeSet;
let mut set = BTreeSet::new();
set.insert(5);
set.insert(1);
set.insert(3);
// 自动排序
for v in &set {
println!("{}", v); // 1, 3, 5
}
// 获取最小/最大值
println!("{:?}", set.first()); // Some(1)
println!("{:?}", set.last()); // Some(5)
6.3 、哈希容器 vs 有序容器
| 特性 | HashMap / HashSet | BTreeMap / BTreeSet |
|---|---|---|
| 查找复杂度 | 平均 O(1) | O(log n) |
| 遍历顺序 | 无序 | 按键排序 |
| 内存占用 | 较高(哈希表开销) | 较低(树节点) |
| 范围查询 | 不支持 | 支持 |
| 适用场景 | 快速查找、无需排序 | 需要有序遍历、范围查询 |
7、 其他常用容器
7.1、 VecDeque:双端队列
VecDeque<T> 支持在两端高效地插入和删除元素,适合实现队列和栈。
rust
use std::collections::VecDeque;
let mut deque = VecDeque::new();
deque.push_back(1);
deque.push_back(2);
deque.push_front(0);
println!("{:?}", deque); // [0, 1, 2]
let front = deque.pop_front(); // Some(0)
let back = deque.pop_back(); // Some(2)
7.2、 LinkedList:双向链表
LinkedList<T> 在 Rust 标准库中可用,但由于缓存不友好,大多数场景下性能不如 Vec 或 VecDeque。仅在需要频繁在中间位置插入/删除且不关心缓存性能时考虑使用。
rust
use std::collections::LinkedList;
let mut list = LinkedList::new();
list.push_back(1);
list.push_back(2);
list.push_front(0);
7.3 、BinaryHeap:二叉堆
BinaryHeap<T> 实现了一个最大堆,适合实现优先队列。
rust
use std::collections::BinaryHeap;
let mut heap = BinaryHeap::new();
heap.push(3);
heap.push(1);
heap.push(5);
println!("{:?}", heap.peek()); // Some(&5)
println!("{:?}", heap.pop()); // Some(5)
8、 容器选择决策指南
面对不同的业务场景,选择合适的容器至关重要。以下决策流程可以帮助你快速做出选择:
#mermaid-svg-OVDyneLHEKiWId97{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-OVDyneLHEKiWId97 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OVDyneLHEKiWId97 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OVDyneLHEKiWId97 .error-icon{fill:#552222;}#mermaid-svg-OVDyneLHEKiWId97 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OVDyneLHEKiWId97 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OVDyneLHEKiWId97 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OVDyneLHEKiWId97 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OVDyneLHEKiWId97 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OVDyneLHEKiWId97 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OVDyneLHEKiWId97 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OVDyneLHEKiWId97 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OVDyneLHEKiWId97 .marker.cross{stroke:#333333;}#mermaid-svg-OVDyneLHEKiWId97 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OVDyneLHEKiWId97 p{margin:0;}#mermaid-svg-OVDyneLHEKiWId97 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-OVDyneLHEKiWId97 .cluster-label text{fill:#333;}#mermaid-svg-OVDyneLHEKiWId97 .cluster-label span{color:#333;}#mermaid-svg-OVDyneLHEKiWId97 .cluster-label span p{background-color:transparent;}#mermaid-svg-OVDyneLHEKiWId97 .label text,#mermaid-svg-OVDyneLHEKiWId97 span{fill:#333;color:#333;}#mermaid-svg-OVDyneLHEKiWId97 .node rect,#mermaid-svg-OVDyneLHEKiWId97 .node circle,#mermaid-svg-OVDyneLHEKiWId97 .node ellipse,#mermaid-svg-OVDyneLHEKiWId97 .node polygon,#mermaid-svg-OVDyneLHEKiWId97 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-OVDyneLHEKiWId97 .rough-node .label text,#mermaid-svg-OVDyneLHEKiWId97 .node .label text,#mermaid-svg-OVDyneLHEKiWId97 .image-shape .label,#mermaid-svg-OVDyneLHEKiWId97 .icon-shape .label{text-anchor:middle;}#mermaid-svg-OVDyneLHEKiWId97 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-OVDyneLHEKiWId97 .rough-node .label,#mermaid-svg-OVDyneLHEKiWId97 .node .label,#mermaid-svg-OVDyneLHEKiWId97 .image-shape .label,#mermaid-svg-OVDyneLHEKiWId97 .icon-shape .label{text-align:center;}#mermaid-svg-OVDyneLHEKiWId97 .node.clickable{cursor:pointer;}#mermaid-svg-OVDyneLHEKiWId97 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-OVDyneLHEKiWId97 .arrowheadPath{fill:#333333;}#mermaid-svg-OVDyneLHEKiWId97 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-OVDyneLHEKiWId97 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-OVDyneLHEKiWId97 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OVDyneLHEKiWId97 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-OVDyneLHEKiWId97 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OVDyneLHEKiWId97 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-OVDyneLHEKiWId97 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-OVDyneLHEKiWId97 .cluster text{fill:#333;}#mermaid-svg-OVDyneLHEKiWId97 .cluster span{color:#333;}#mermaid-svg-OVDyneLHEKiWId97 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-OVDyneLHEKiWId97 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-OVDyneLHEKiWId97 rect.text{fill:none;stroke-width:0;}#mermaid-svg-OVDyneLHEKiWId97 .icon-shape,#mermaid-svg-OVDyneLHEKiWId97 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OVDyneLHEKiWId97 .icon-shape p,#mermaid-svg-OVDyneLHEKiWId97 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-OVDyneLHEKiWId97 .icon-shape .label rect,#mermaid-svg-OVDyneLHEKiWId97 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OVDyneLHEKiWId97 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-OVDyneLHEKiWId97 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-OVDyneLHEKiWId97 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
是
否
是
否
是
否
是
否
需要存储数据
需要键值关联?
需要按键排序?
需要去重?
BTreeMap
HashMap
需要排序?
需要两端操作?
BTreeSet
HashSet
VecDeque
Vec
8.1、 快速选择表
| 需求 | 推荐容器 |
|---|---|
| 有序列表、随机访问 | Vec |
| 键值对、快速查找 | HashMap |
| 键值对、有序遍历 | BTreeMap |
| 去重、快速判断存在 | HashSet |
| 去重、有序遍历 | BTreeSet |
| 队列 / 双端操作 | VecDeque |
| 优先队列 | BinaryHeap |
9、性能优化与最佳实践
9.1、 预分配容量
rust
// 不推荐:频繁扩容
let mut v = Vec::new();
for i in 0..1000 {
v.push(i);
}
// 推荐:预分配
let mut v = Vec::with_capacity(1000);
for i in 0..1000 {
v.push(i);
}
9.2、 避免不必要的克隆
rust
use std::collections::HashMap;
// 不推荐:克隆字符串
let mut map = HashMap::new();
let key = String::from("key");
map.insert(key.clone(), 1);
// 推荐:直接转移所有权
let mut map = HashMap::new();
let key = String::from("key");
map.insert(key, 1);
9.3 使用 entry API 避免重复查找
rust
use std::collections::HashMap;
let mut map = HashMap::new();
// 不推荐:两次查找
if map.contains_key("key") {
let v = map.get_mut("key").unwrap();
*v += 1;
} else {
map.insert("key", 1);
}
// 推荐:一次查找
*map.entry("key").or_insert(0) += 1;
9.4 、迭代器与容器结合
rust
// 使用迭代器构建容器
let squares: Vec<i32> = (1..=10).map(|x| x * x).collect();
// 分组统计
use std::collections::HashMap;
let words = vec!["apple", "banana", "apple", "cherry"];
let mut counts: HashMap<&str, i32> = HashMap::new();
for word in words {
*counts.entry(word).or_insert(0) += 1;
}
10、 总结
Rust 的标准容器在设计上兼顾了安全性、性能和表达力。本文详细介绍了 Vec、HashMap、HashSet、BTreeMap、BTreeSet 等核心容器,以及 VecDeque、LinkedList、BinaryHeap 等辅助容器。
核心要点回顾:
Vec是最通用的动态数组,适合大多数顺序存储场景。HashMap提供 O(1) 平均查找,是无序键值存储的首选。HashSet适合去重和成员判断。BTreeMap/BTreeSet在需要有序遍历和范围查询时更优。- 合理使用
with_capacity、entryAPI 和迭代器可以显著提升代码质量和性能。
掌握这些容器的特性与适用场景,是写出高效、优雅 Rust 代码的重要一步。建议在实际项目中多实践,逐步建立对不同容器性能特征的直觉。
二、代码示例
rust
use std::collections::{
BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque,
};
use std::cmp::Reverse;
fn main() {
// ===================== 1. Vec<T> 动态数组(最常用) =====================
println!("===== Vec =====");
let mut vec = Vec::with_capacity(5); // 预分配容量
vec.push(10);
vec.push(20);
vec.push(30);
println!("len={}, cap={}", vec.len(), vec.capacity());
println!("index[0] = {}", vec[0]); // 下标访问,越界panic
if let Some(v) = vec.get(2) { // get 返回Option,安全
println!("get(2) = {}", v);
}
vec.pop();
println!("after pop: {:?}", vec);
// 遍历:借用,不拿走所有权
for x in &vec {
println!("item: {}", x);
}
// ===================== 2. VecDeque<T> 双端队列 =====================
println!("\n===== VecDeque =====");
let mut deque = VecDeque::new();
deque.push_back(1);
deque.push_front(0);
deque.push_back(2);
println!("deque: {:?}", deque);
deque.pop_front(); // 头删
deque.pop_back(); // 尾删
println!("after pop front/back: {:?}", deque);
// ===================== 3. LinkedList<T> 双向链表 =====================
println!("\n===== LinkedList =====");
let mut list1 = LinkedList::new();
list1.push_back(100);
list1.push_back(200);
let mut list2 = LinkedList::new();
list2.push_back(999);
list1.append(&mut list2); // O(1) 把list2全部转移到list1,list2变空
println!("list1 {:?}, list2 {:?}", list1, list2);
// ===================== 4. HashMap<K,V> 哈希map,无序 =====================
println!("\n===== HashMap =====");
let mut hash_map = HashMap::new();
hash_map.insert("apple", 5);
hash_map.insert("banana", 3);
// entry API,高频!不存在则插入
hash_map.entry("orange").or_insert(10);
hash_map.entry("apple").or_insert(99); // apple已存在,不会修改
println!("apple value {:?}", hash_map.get("apple"));
for (k, v) in &hash_map {
println!("{} -> {}", k, v);
}
// ===================== 5. BTreeMap<K,V> B树map,按键有序 =====================
println!("\n===== BTreeMap =====");
let mut btree_map = BTreeMap::new();
btree_map.insert(3, "three");
btree_map.insert(1, "one");
btree_map.insert(2, "two");
// 自动按key升序遍历
for (k, v) in &btree_map {
println!("{} -> {}", k, v);
}
// 范围查询 range
println!("range 1..=2:");
for (k, v) in btree_map.range(1..=2) {
println!("{} -> {}", k, v);
}
// ===================== 6. HashSet<T> 哈希集合,去重无序 =====================
println!("\n===== HashSet =====");
let mut hash_set = HashSet::new();
hash_set.insert(1);
hash_set.insert(2);
hash_set.insert(1); // 重复插入无效
println!("contains 1: {}", hash_set.contains(&1));
println!("hash_set {:?}", hash_set);
// ===================== 7. BTreeSet<T> B树集合,有序去重 =====================
println!("\n===== BTreeSet =====");
let mut btree_set = BTreeSet::new();
btree_set.insert(5);
btree_set.insert(1);
btree_set.insert(3);
for x in &btree_set {
println!("{}", x); // 输出 1 3 5
}
// ===================== 8. BinaryHeap 优先队列(默认大顶堆) =====================
println!("\n===== BinaryHeap 大顶堆 =====");
let mut max_heap = BinaryHeap::new();
max_heap.push(2);
max_heap.push(8);
max_heap.push(5);
println!("max peek {:?}", max_heap.peek());
while let Some(val) = max_heap.pop() {
println!("pop {}", val); // 8,5,2
}
// 小顶堆 Reverse
println!("\n===== BinaryHeap 小顶堆 Reverse =====");
let mut min_heap = BinaryHeap::new();
min_heap.push(Reverse(2));
min_heap.push(Reverse(8));
min_heap.push(Reverse(5));
while let Some(Reverse(val)) = min_heap.pop() {
println!("pop {}", val); // 2,5,8
}
// ========== 遍历所有权小知识点 ==========
println!("\n===== 遍历所有权演示 =====");
let data = vec![10,20,30];
for _item in &data { /* 借用,data继续可用 */ }
println!("data still alive {:?}", data);
for _item in data { /* 转移所有权,data失效 */ }
// println!("{:?}", data); // compile error!
}
rust
Blocking waiting for file lock on artifact directory
Compiling modbus-debug-assistant v0.1.0 (E:\leaning\slint\test)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 20.77s
Running `target\debug\modbus-debug-assistant.exe`
===== Vec =====
len=3, cap=5
index[0] = 10
get(2) = 30
after pop: [10, 20]
item: 10
item: 20
===== VecDeque =====
deque: [0, 1, 2]
after pop front/back: [1]
===== LinkedList =====
list1 [100, 200, 999], list2 []
===== HashMap =====
apple value Some(5)
apple -> 5
banana -> 3
orange -> 10
===== BTreeMap =====
1 -> one
2 -> two
3 -> three
range 1..=2:
1 -> one
2 -> two
===== HashSet =====
contains 1: true
hash_set {1, 2}
===== BTreeSet =====
1
3
5
===== BinaryHeap 大顶堆 =====
max peek Some(8)
pop 8
pop 5
pop 2
===== BinaryHeap 小顶堆 Reverse =====
pop 2
pop 5
pop 8
===== 遍历所有权演示 =====
data still alive [10, 20, 30]
PS E:\leaning\slint\test>
