第10章:常用集合
第10章:常用集合
10.1 Vec:动态数组
创建与初始化
fn main() {
// 创建空 Vec
let mut v: Vec<i32> = Vec::new();
// 使用宏创建(类型推断)
let v2 = vec![1, 2, 3, 4, 5];
// 创建指定容量的 Vec(避免频繁重新分配)
let v3: Vec<i32> = Vec::with_capacity(100);
// 创建包含相同元素的 Vec
let v4 = vec![0; 10]; // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
println!("v2 = {:?}", v2);
println!("v3 长度 = {}, 容量 = {}", v3.len(), v3.capacity());
println!("v4 = {:?}", v4);
}
添加和删除元素
fn main() {
let mut v = vec![1, 2, 3];
// push: 在末尾添加
v.push(4);
v.push(5);
println!("push后: {:?}", v); // [1, 2, 3, 4, 5]
// pop: 移除并返回最后一个元素
let last = v.pop();
println!("pop: {:?}, 剩余: {:?}", last, v); // Some(5), [1, 2, 3, 4]
// insert: 在指定位置插入
v.insert(1, 10);
println!("insert(1, 10): {:?}", v); // [1, 10, 2, 3, 4]
// remove: 移除指定位置的元素
let removed = v.remove(1);
println!("remove(1)={}, 剩余: {:?}", removed, v); // 10, [1, 2, 3, 4]
// retain: 保留满足条件的元素
v.retain(|&x| x > 2);
println!("retain(>2): {:?}", v); // [3, 4]
// clear: 清空
v.clear();
println!("clear后: len={}", v.len()); // 0
}
访问元素
fn main() {
let v = vec![10, 20, 30, 40, 50];
// 索引访问(越界会 panic)
let third = v[2];
println!("第三个元素: {}", third); // 30
// get 方法(返回 Option,不会 panic)
match v.get(2) {
Some(val) => println!("第三个元素: {}", val),
None => println!("索引越界"),
}
match v.get(10) {
Some(val) => println!("第十一个元素: {}", val),
None => println!("索引10不存在"),
}
// first / last
println!("第一个: {:?}", v.first()); // Some(10)
println!("最后一个: {:?}", v.last()); // Some(50)
// 切片
let slice = &v[1..4];
println!("切片[1..4]: {:?}", slice); // [20, 30, 40]
}
遍历
fn main() {
let v = vec![1, 2, 3, 4, 5];
// 不可变遍历
for val in &v {
print!("{} ", val);
}
println!();
// 可变遍历
let mut v = v;
for val in &mut v {
*val *= 2;
}
println!("翻倍后: {:?}", v); // [2, 4, 6, 8, 10]
// 带索引遍历
for (i, val) in v.iter().enumerate() {
println!("v[{}] = {}", i, val);
}
// 消耗性遍历(获取所有权)
for val in v {
print!("{} ", val);
}
println!();
// println!("{:?}", v); // ❌ v 已被消耗
}
排序与搜索
fn main() {
let mut v = vec![5, 3, 1, 4, 2];
// 排序
v.sort();
println!("升序: {:?}", v); // [1, 2, 3, 4, 5]
v.sort_by(|a, b| b.cmp(a));
println!("降序: {:?}", v); // [5, 4, 3, 2, 1]
// 浮点数排序(需要处理 NaN)
let mut floats = vec![3.14, 1.41, 2.72, 0.58];
floats.sort_by(|a, b| a.partial_cmp(b).unwrap());
println!("浮点排序: {:?}", floats);
// 二分搜索(需要已排序)
v.sort();
match v.binary_search(&3) {
Ok(index) => println!("找到3在位置: {}", index),
Err(index) => println!("未找到3,应插入位置: {}", index),
}
// 包含检查
println!("包含4: {}", v.contains(&4)); // true
println!("位置: {:?}", v.iter().position(|&x| x == 4)); // Some(3)
}
Vec 与内存
fn main() {
let mut v: Vec<i32> = Vec::with_capacity(10);
println!("初始: len={}, capacity={}", v.len(), v.capacity());
for i in 0..15 {
v.push(i);
println!("push {}: len={}, capacity={}", i, v.len(), v.capacity());
}
// 收缩以适应长度
v.shrink_to_fit();
println!("收缩后: len={}, capacity={}", v.len(), v.capacity());
}
10.2 HashMap<K, V>:哈希映射
创建与操作
use std::collections::HashMap;
fn main() {
// 创建
let mut scores: HashMap<String, i32> = HashMap::new();
// 插入
scores.insert("Alice".to_string(), 95);
scores.insert("Bob".to_string(), 87);
scores.insert("Charlie".to_string(), 92);
// 从元组集合创建
let teams = vec![("Blue", 10), ("Red", 50)];
let team_scores: HashMap<&str, i32> = teams.into_iter().collect();
// 获取值
let alice_score = scores.get("Alice");
println!("Alice: {:?}", alice_score); // Some(95)
let unknown = scores.get("Unknown");
println!("Unknown: {:?}", unknown); // None
// 遍历
for (name, score) in &scores {
println!("{}: {}", name, score);
}
}
Entry API
use std::collections::HashMap;
fn main() {
let mut map: HashMap<&str, Vec<i32>> = HashMap::new();
// entry: 不存在则插入默认值,返回可变引用
map.entry("scores").or_insert_with(Vec::new).push(95);
map.entry("scores").or_insert_with(Vec::new).push(87);
map.entry("scores").or_insert_with(Vec::new).push(92);
println!("{:?}", map["scores"]); // [95, 87, 92]
// or_insert: 简单版本
let mut counts = HashMap::new();
for word in "hello world hello rust hello".split_whitespace() {
let count = counts.entry(word).or_insert(0);
*count += 1;
}
println!("词频: {:?}", counts);
// and_modify: 已存在时修改
let mut settings: HashMap<&str, i32> = HashMap::new();
settings.entry("timeout").or_insert(30);
settings.entry("timeout").and_modify(|e| *e += 10);
println!("{:?}", settings); // {"timeout": 40}
}
常用方法
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("a", 1);
map.insert("b", 2);
map.insert("c", 3);
println!("长度: {}", map.len());
println!("包含a: {}", map.contains_key("a"));
println!("值a: {:?}", map.get("a"));
// 删除
map.remove("a");
println!("删除a后: {:?}", map);
// 遍历
for (key, value) in &map {
println!("{}: {}", key, value);
}
// 保留满足条件的条目
map.retain(|_, v| *v > 1);
println!("retain(>1): {:?}", map);
}
10.3 BTreeMap<K, V>:有序映射
use std::collections::BTreeMap;
fn main() {
let mut map = BTreeMap::new();
map.insert(3, "three");
map.insert(1, "one");
map.insert(4, "four");
map.insert(1, "ONE"); // 覆盖
// 按键排序遍历
for (key, value) in &map {
println!("{}: {}", key, value);
}
// 范围查询
let range: Vec<_> = map.range(2..=4).collect();
println!("2..=4: {:?}", range);
// 获取最小/最大
println!("最小: {:?}", map.iter().next());
println!("最大: {:?}", map.iter().next_back());
}
HashMap vs BTreeMap
| 特性 | HashMap | BTreeMap |
|---|
| 有序性 | 无序 | 按键排序 |
| 查找复杂度 | O(1) 平均 | O(log n) |
| 插入复杂度 | O(1) 平均 | O(log n) |
| 范围查询 | 不支持 | ✅ 支持 |
| 键要求 | Hash + Eq | Ord |
| 适用场景 | 快速查找 | 需要排序/范围查询 |
10.4 HashSet:哈希集合
use std::collections::HashSet;
fn main() {
// 创建
let mut set: HashSet<i32> = HashSet::new();
set.insert(1);
set.insert(2);
set.insert(3);
set.insert(2); // 重复元素会被忽略
println!("集合: {:?}", set);
println!("长度: {}", set.len());
// 从数组创建
let set2: HashSet<i32> = vec![3, 4, 5].into_iter().collect();
// 集合操作
println!("包含2: {}", set.contains(&2));
// 交集
let intersection: Vec<_> = set.intersection(&set2).collect();
println!("交集: {:?}", intersection); // [3]
// 并集
let union: Vec<_> = set.union(&set2).collect();
println!("并集: {:?}", union);
// 差集
let difference: Vec<_> = set.difference(&set2).collect();
println!("差集: {:?}", difference); // [1, 2]
// 对称差集
let sym_diff: Vec<_> = set.symmetric_difference(&set2).collect();
println!("对称差: {:?}", sym_diff); // [1, 2, 4, 5]
// 判断关系
let a: HashSet<i32> = vec![1, 2, 3].into_iter().collect();
let b: HashSet<i32> = vec![1, 2, 3, 4, 5].into_iter().collect();
println!("a 是 b 的子集: {}", a.is_subset(&b)); // true
println!("b 是 a 的超集: {}", b.is_superset(&a)); // true
}
去重
fn main() {
let numbers = vec![1, 2, 3, 2, 1, 4, 5, 4];
// 使用 HashSet 去重(不保持顺序)
let unique: HashSet<_> = numbers.iter().collect();
println!("去重(无序): {:?}", unique);
// 保持顺序去重
let mut seen = HashSet::new();
let unique_ordered: Vec<_> = numbers
.iter()
.filter(|x| seen.insert(**x))
.collect();
println!("去重(有序): {:?}", unique_ordered); // [1, 2, 3, 4, 5]
}
10.5 BTreeSet:有序集合
use std::collections::BTreeSet;
fn main() {
let mut set = BTreeSet::new();
set.insert(5);
set.insert(2);
set.insert(8);
set.insert(1);
set.insert(5); // 重复,忽略
// 自动排序遍历
println!("有序集合: {:?}", set); // {1, 2, 5, 8}
// 范围查询
let range: Vec<_> = set.range(3..=7).collect();
println!("3..=7: {:?}", range); // [5]
}
10.6 迭代器与集合操作
收集到集合
use std::collections::{HashMap, BTreeMap, HashSet};
fn main() {
let v = vec![1, 2, 3, 4, 5];
// Vec → HashSet
let set: HashSet<_> = v.iter().cloned().collect();
println!("HashSet: {:?}", set);
// 元组 → HashMap
let pairs = vec![("a", 1), ("b", 2), ("c", 3)];
let map: HashMap<&str, i32> = pairs.into_iter().collect();
println!("HashMap: {:?}", map);
// 元组 → BTreeMap
let btree: BTreeMap<&str, i32> = vec![("c", 3), ("a", 1), ("b", 2)]
.into_iter()
.collect();
println!("BTreeMap (有序): {:?}", btree);
}
常用迭代器操作
fn main() {
let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// filter: 过滤
let evens: Vec<_> = numbers.iter().filter(|&&x| x % 2 == 0).collect();
println!("偶数: {:?}", evens); // [2, 4, 6, 8, 10]
// map: 转换
let doubled: Vec<_> = numbers.iter().map(|x| x * 2).collect();
println!("翻倍: {:?}", doubled);
// filter + map 链式调用
let even_squares: Vec<_> = numbers
.iter()
.filter(|&&x| x % 2 == 0)
.map(|x| x * x)
.collect();
println!("偶数的平方: {:?}", even_squares); // [4, 16, 36, 64, 100]
// fold: 归约
let sum = numbers.iter().fold(0, |acc, &x| acc + x);
println!("总和: {}", sum); // 55
// any / all
println!("有偶数: {}", numbers.iter().any(|x| x % 2 == 0)); // true
println!("全是正数: {}", numbers.iter().all(|&x| x > 0)); // true
// find
let first_even = numbers.iter().find(|&&x| x % 2 == 0);
println!("第一个偶数: {:?}", first_even); // Some(2)
// position
let pos = numbers.iter().position(|&x| x == 5);
println!("5的位置: {:?}", pos); // Some(4)
}
10.7 业务场景示例
访问日志分析
use std::collections::HashMap;
#[derive(Debug)]
struct LogEntry {
path: String,
status: u16,
response_time_ms: u32,
}
fn analyze_logs(logs: &[LogEntry]) {
let mut path_counts: HashMap<&str, u32> = HashMap::new();
let mut status_counts: HashMap<u16, u32> = HashMap::new();
let mut path_total_time: HashMap<&str, u64> = HashMap::new();
for log in logs {
*path_counts.entry(&log.path).or_insert(0) += 1;
*status_counts.entry(log.status).or_insert(0) += 1;
*path_total_time.entry(&log.path).or_insert(0) += log.response_time_ms as u64;
}
println!("=== 访问统计 ===");
println!("总请求数: {}", logs.len());
println!("\n--- 热门路径 (Top 5) ---");
let mut paths: Vec<_> = path_counts.iter().collect();
paths.sort_by(|a, b| b.1.cmp(a.1));
for (path, count) in paths.iter().take(5) {
let avg_time = path_total_time[*path] / **count as u64;
println!(" {} ({}次, 平均{}ms)", path, count, avg_time);
}
println!("\n--- 状态码分布 ---");
let mut statuses: Vec<_> = status_counts.iter().collect();
statuses.sort_by_key(|&(k, _)| k);
for (status, count) in &statuses {
println!(" {} ({}次)", status, count);
}
}
fn main() {
let logs = vec![
LogEntry { path: "/api/users".to_string(), status: 200, response_time_ms: 50 },
LogEntry { path: "/api/users".to_string(), status: 200, response_time_ms: 45 },
LogEntry { path: "/api/users".to_string(), status: 500, response_time_ms: 200 },
LogEntry { path: "/api/orders".to_string(), status: 200, response_time_ms: 80 },
LogEntry { path: "/api/orders".to_string(), status: 200, response_time_ms: 90 },
LogEntry { path: "/api/items".to_string(), status: 200, response_time_ms: 30 },
LogEntry { path: "/api/items".to_string(), status: 404, response_time_ms: 10 },
LogEntry { path: "/health".to_string(), status: 200, response_time_ms: 5 },
];
analyze_logs(&logs);
}
频率统计工具
use std::collections::HashMap;
fn word_frequency(text: &str, top_n: usize) -> Vec<(String, usize)> {
let mut freq: HashMap<String, usize> = HashMap::new();
for word in text
.split_whitespace()
.map(|w| w.trim_matches(|c: char| !c.is_alphanumeric()))
.filter(|w| !w.is_empty())
{
let word = word.to_lowercase();
*freq.entry(word).or_insert(0) += 1;
}
let mut result: Vec<_> = freq.into_iter().collect();
result.sort_by(|a, b| b.1.cmp(&a.1));
result.truncate(top_n);
result
}
fn main() {
let text = "Rust is a systems programming language. \
Rust is fast. Rust is safe. \
Rust has ownership. Rust prevents data races. \
Programming in Rust is fun. \
Rust is loved by developers.";
let top_words = word_frequency(text, 10);
println!("词频统计 (Top 10):");
println!("{:<15} {:<8} {}", "单词", "次数", "柱状图");
println!("{}", "-".repeat(40));
let max_count = top_words.first().map_or(0, |(_, c)| *c);
for (word, count) in &top_words {
let bar_len = (*count as f64 / max_count as f64 * 20.0) as usize;
let bar: String = "█".repeat(bar_len);
println!("{:<15} {:<8} {}", word, count, bar);
}
}
10.8 本章小结
| 集合 | 特点 | 适用场景 |
|---|
Vec<T> | 有序、可增长 | 通用列表、栈 |
HashMap<K,V> | 无序、O(1)查找 | 快速键值查找 |
BTreeMap<K,V> | 有序、O(log n)查找 | 需要排序/范围查询 |
HashSet<T> | 无序、无重复 | 去重、集合运算 |
BTreeSet<T> | 有序、无重复 | 排序去重、范围查询 |
扩展阅读
- Rust Book - 集合 — 官方教程
- std::collections 文档 — 集合类型总览
- hashbrown crate — 更快的哈希表实现