Rust 相关容器(集合)详解

这里写目录标题

  • [一、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,以及有序集合 BTreeMapBTreeSet。我们会从基本用法出发,逐步深入到内存布局、性能特性和最佳实践,帮助你根据实际场景选择最合适的容器。

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 的键,类型必须实现 HashEq 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:有序容器

当需要按键的顺序遍历数据时,BTreeMapBTreeSet 是比哈希容器更合适的选择。

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 标准库中可用,但由于缓存不友好,大多数场景下性能不如 VecVecDeque。仅在需要频繁在中间位置插入/删除且不关心缓存性能时考虑使用。

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 的标准容器在设计上兼顾了安全性、性能和表达力。本文详细介绍了 VecHashMapHashSetBTreeMapBTreeSet 等核心容器,以及 VecDequeLinkedListBinaryHeap 等辅助容器。

核心要点回顾

  • Vec 是最通用的动态数组,适合大多数顺序存储场景。
  • HashMap 提供 O(1) 平均查找,是无序键值存储的首选。
  • HashSet 适合去重和成员判断。
  • BTreeMap / BTreeSet 在需要有序遍历和范围查询时更优。
  • 合理使用 with_capacityentry API 和迭代器可以显著提升代码质量和性能。

掌握这些容器的特性与适用场景,是写出高效、优雅 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> 
相关推荐
萧瑟余晖4 小时前
Java深入解析篇三十三之密封类与接口(Sealed Classes)详解
java·开发语言
上学的小垃圾7 小时前
基于docker安装MySQL(openEuler系统)
linux·mysql·docker·容器
论迹复利8 小时前
FreeRTOS 在 RISC-V 上是如何“点火“的 —— 从 main() 到第一个任务的完整链路
java·开发语言·risc-v
张宇Joaquin8 小时前
鲲鹏统一并行加速库KUPL--众核并行能力介绍
java·开发语言·网络
736c8 小时前
C语言-数组 07
c语言·开发语言
宸津-代码粉碎机8 小时前
AI攻防战升级!基于Spring AI构建Java应用自动免疫安全体系
java·大数据·开发语言·人工智能·python·安全·spring
LorryJovens10 小时前
【LAAP科研】CEN因果等价网络理论---从双缝干涉到因果等价
开发语言·php
Brilliantwxx11 小时前
【Linux】 进程(10) 进程控制深度解析:创建、终止与等待
linux·运维·服务器·c语言·开发语言·网络