第八章:集合类型 (Collections) —— 数组与哈希表

Unknown Author 独酌
2025-11-21 Rust, Book

好的,搞定了抽象层,我们回到最实用的数据存储上来。 在 JS 里,我们几乎只用 Array [] 和 Object {}。 在 Rust 里,我们也有一组对应的强力工具。

1. Vector (Vec<T>) —— 动态数组

Rust 里的原生数组(Array)长度是固定的(写死的)。这显然不够用。 我们在 JS 里习惯使用的那个“想塞多少就塞多少”的数组,在 Rust 里叫 Vector (向量),简称 Vec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fn main() {
// 创建一个空的 Vector,如果不塞数据,必须指定类型
let mut numbers: Vec<i32> = Vec::new();

// 或者用宏来快速创建
let mut todos = vec!["Learn Rust", "Sleep"];

// 推入数据 (就像 JS 的 .push())
todos.push("Eat");

// 读取数据
// 注意:为了防止越界 (Index out of bounds),Rust 推荐用 .get()
match todos.get(0) {
Some(task) => println!("首要任务: {}", task),
None => println!("没有任务了!"),
}
}

注意点: Vec 也是分配在堆(Heap)上的,所以它也遵守所有权规则。当 todos 离开作用域,它里面的所有字符串也会被一起清理掉。

2. String vs &str —— 字符串的“人格分裂”

这是前端开发者学 Rust 最痛苦的地方,没有之一。

在 JS 里,字符串就是字符串。 在 Rust 里,字符串有两种主要形式:

  1. String (大写 S):
  • 所有者: 你拥有它。
  • 可变: 可以修改、变长。
  • 位置: 存储在堆 (Heap) 上。
  • 类比: 像是一个完整的 Word 文档文件。
  1. &str (字符串切片/引用):
  • 借用者: 你只是借来看一眼。
  • 不可变: 通常指向字面量或 String 的一部分。
  • 位置: 栈 (Stack) 或 静态内存区。
  • 类比: 像是 Word 文档里选中一段文字的“高亮区域”截图。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fn main() {
// 这是一个 &str (字面量,编译进二进制文件里了,不可改)
let s1 = "Hello";

// 这是一个 String (从 &str 转换而来,存堆上,可以改)
let mut s2 = String::from(s1);
s2.push_str(", World!");

print_it(s1); // 传 &str
print_it(&s2); // &s2 会自动转换成 &str,这叫"解引用强制转换"
}

// 参数通常写 &str,这样既能接字面量,也能接 String 的引用,通用性最强
fn print_it(s: &str) {
println!("{}", s);
}

💡经验之谈: 如果你是写库函数的作者,参数尽量用 &str;如果你是处理业务逻辑需要拥有数据,用 String

3. HashMap —— 真正的 KV 存储

这就像 JS 中的 Map 或者普通的 Object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use std::collections::HashMap;

fn main() {
let mut scores = HashMap::new();

// 插入数据
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);

// 获取数据
let team_name = String::from("Blue");
// .get 返回的是 Option<&i32>,因为可能取不到
if let Some(score) = scores.get(&team_name) {
println!("分数: {}", score);
}
}

🧠 随堂小测验

关于 String&str,请看下面的代码。

1
2
3
4
fn main() {
let my_name = "Gemini"; // 变量 my_name 的类型是 A
let my_string = my_name.to_string(); // 变量 my_string 的类型是 B
}

请分别说出 A 和 B 的类型是什么?

  1. A: String, B: &str
  2. A: &str, B: String
  3. 都是 String
独酌

独酌

小镇码农

相关文章