Rust 学习笔记 12:常用集合 (Collections)

“Data structures are the backbone of any program.”

Rust 标准库提供了一系列非常实用的集合数据结构。和数组/元组不同,它们的数据存储在堆 (Heap) 上,这意味着长度可以动态变化。

如果你有 Go 语言背景,可以这样类比:

  • Vec<T> ≈ Slice []T
  • Stringstring (但在 Rust 中它是可变的)
  • HashMap<K, V> ≈ Map map[K]V

1. Vector (动态数组)

Vector 是最常用的集合。

1let mut v: Vec<i32> = Vec::new();
2v.push(1);
3v.push(2);
4v.push(3);

或者使用 vec! 宏:

1let v = vec![1, 2, 3];

访问元素: 有两种方式,一种是索引 &v[2](越界会 Panic),一种是 v.get(2)(返回 Option<&T>)。在 Rust 中,推荐尽可能用 get 来安全处理越界。

借用规则陷阱: 当你持有一个元素的引用时,不能往 Vector 里 push 新元素! 原因:push 可能会导致 vector 扩容(重新分配内存),如果你手里还攥着旧内存的引用,那就是悬垂指针了。Rust 编译器会死死盯着你。

2. String (UTF-8 字符串)

Rust 的字符串处理有点复杂,因为它彻底贯彻了 UTF-8。

String 是可变的、堆分配的字符串。而 &str 是切片(通常指向编译入二进制的静态区,或是 String 的一部分)。

拼接

1let s1 = String::from("Hello, ");
2let s2 = String::from("world!");
3let s3 = s1 + &s2; 

注意右边必须是引用 &s2。而且 s1 在这里被移动了,后面不能再用了。这和 add 函数的签名 fn add(self, s: &str) -> String 有关。

更推荐用 format! 宏:

1let s = format!("{}-{}", s1, s2);

它不会夺走所有权。

索引s[0] 在 Rust 中是非法的!因为 UTF-8 是变长编码,有些字符占 1 字节,有些占 3 字节。直接按字节索引得到的未必是有效字符。

3. HashMap (哈希表)

除了 use std::collections::HashMap; 这一步比 Go 麻烦点,其他用法很像。

所有权: 对于实现了 Copy trait 的类型(如 i32),值会被拷贝进 HashMap。对于 String,所有权会被移动进 HashMap。

Entry API: 这是 Rust HashMap 最优雅的设计。 比如统计单词词频,在 Go 里可能要写 if v, ok := map[key]; ok { ... } else { ... }。 在 Rust 里:

1let mut scores = HashMap::new();
2scores.entry(String::from("Blue")).or_insert(50);

如果键不存在就插入 50,如果存在就返回已有的值的引用。

1let count = map.entry(word).or_insert(0);
2*count += 1;

这一行代码完成了"查找-不存在则初始化-返回引用-解引用加一"的全套操作,既高效又易读。

4. 小结

第十二篇笔记。

  • Vector 是主力数组。
  • String 真的很复杂,因为 UTF-8 很复杂。
  • HashMap 的 Entry API 是神器。

下一篇,我们将探讨 错误处理 (Error Handling)。 panic? Result? Option? ?操作符? Rust 的错误处理哲学是:“如果可能出错,就把它写在类型签名里,逼调用者处理。”


练习题

  1. 给定一个整数列表,使用 Vector 和 HashMap 计算它的平均值 (mean)、中位数 (median) 和众数 (mode)。
  2. 将字符串 “apple” 转换成 Pig Latin(猪拉丁语):元音开头加 “-hay” (apple-hay),辅音开头把首字母移到最后加 “-ay” (first-irst-fay)。

思考题

为什么 Rust 不允许通过整数索引 s[0] 访问字符串字符?这体现了 Rust 在"易用性"和"正确性"之间做出了怎样的权衡?


本文代码示例

关注公众号:极客老墨

更多 AI 应用开发、工程实践和效率工具分享,欢迎扫码关注。

极客老墨微信公众号二维码

相关阅读