强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

第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

特性HashMapBTreeMap
有序性无序按键排序
查找复杂度O(1) 平均O(log n)
插入复杂度O(1) 平均O(log n)
范围查询不支持✅ 支持
键要求Hash + EqOrd
适用场景快速查找需要排序/范围查询

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>有序、无重复排序去重、范围查询

扩展阅读

  1. Rust Book - 集合 — 官方教程
  2. std::collections 文档 — 集合类型总览
  3. hashbrown crate — 更快的哈希表实现