type
Post
date
Nov 3, 2025
slug
Rust/notebook/8
summary
学习下 Rust 圣经,记录笔记
status
Published
tags
Rust
category
技术茶点
icon
password
😀
Rust 标准库提供了三种常用的、可变大小且数据存储在堆上的集合数据结构:向量vector,用于储存一系列数量可变的值)、字符串String,字符的集合)和哈希 maphash map,用于将值与特定的键相关联)。

8.常见集合

8.1.使用Vector储存列表

概念
含义
关键点
向量(Vec)
Rust 中的动态数组/可增长的集合,元素类型相同。 (doc.rust-lang.org)
存储多个值在连续内存中;元素类型必须统一。 (doc.rust-lang.org)
创建新向量
使用 Vec::new()vec![] 宏。 (doc.rust-lang.org)
若为空创建,则可能需要类型注解;使用 vec![1,2,3] 时类型可被推导。 (doc.rust-lang.org)
修改/添加元素
使用 push() 方法。 (doc.rust-lang.org)
向量要是可变(mut)才能调用 push。 (Massachusetts Institute of Technology)
访问元素
两种方式:索引语法 &v[index]v.get(index) 返回 Option<&T>。 (doc.rust-lang.org)
索引语法超出边界会 panicget 方法安全地返回 None。 (doc.rust-lang.org)
遍历(迭代)
使用 for 循环遍历引用;如要修改元素则用可变引用。 (doc.rust-lang.org)
如:for i in &v { … }(只读)或 for i in &mut v { *i += … }(修改) (doc.rust-lang.org)
不同类型元素存储
向量只能存储同一类型;若需存储多种类型可用 enum。 (doc.rust-lang.org)
例如定义 enum SpreadsheetCell { Int(i32), Float(f64), Text(String) },然后 Vec<SpreadsheetCell>。 (doc.rust-lang.org)
所有权/借用注意事项
向量可能重新分配内存,导致已有引用无效。 (doc.rust-lang.org)
例如若持有 &v[0],然后又 v.push(...),可能导致引用悬空。 (doc.rust-lang.org)
概念
说明
示例
Vec<T>
可增长的、存放相同类型元素的动态数组
let v: Vec<i32> = Vec::new();
vec![]
创建并初始化 vector
let v = vec![1, 2, 3];
可变 vector
用于添加元素
let mut v = Vec::new(); v.push(5);
访问元素
索引或 get() 方法
&v[2]v.get(2)
越界访问
索引会 panic,get() 返回 Option
v[100] ❌ → panic;v.get(100) ✅ → None
遍历
for 循环可遍历所有元素
for i in &v { println!("{}", i); }
可变遍历
for i in &mut v { *i += 50; }
删除
vector 离开作用域自动释放
Rust 自动调用 drop

8.2.使用字符串储存UTF-8编码的文本

 
场景
正确示例
常见错误 or 注意点
创建字符串
rust<br>let s = String::from("hello");<br>let s2 = "你好".to_string();
String::new() 创建空字符串,不含内容。
追加字符串
rust<br>let mut s = String::from("foo");<br>s.push_str("bar");
push_str 接受 &str,不会转移所有权。
追加单个字符
rust<br>let mut s = String::from("lo");<br>s.push('l');
push() 只能接收单个 char
字符串连接(+)
rust<br>let s1 = String::from("Hello, ");<br>let s2 = String::from("world!");<br>let s3 = s1 + &s2;
+ 运算会 移动 s1 的所有权,之后不能再用 s1
字符串连接(推荐:format!)
rust<br>let s1 = String::from("tic");<br>let s2 = String::from("tac");<br>let s3 = String::from("toe");<br>let s = format!("{s1}-{s2}-{s3}");
format! 不会移动所有权,最安全。
访问字符
rust<br>for c in "你好".chars() { println!("{}", c); }
不能用 s[0] 索引字符串,会编译错误。
获取字节
rust<br>for b in "你好".bytes() { println!("{}", b); }
.bytes() 返回每个 UTF-8 字节,不等于“字符”。
切片(要在字符边界上)
rust<br>let hello = "Здравствуйте";<br>let s = &hello[0..4]; // 取前两个字母
如果切片不是在字符边界(如 [0..1]),会 panic。

8.3.使用Hash Map储存键值对

概念
含义
关键点
HashMap<K, V>
用键 (K) 映射值 (V) 的集合。适用于通过任意类型的键查找值,而不是像向量那样按索引查找。 (doc.rust-lang.org)
键和值的类型分别必须一致:所有键类型相同,所有值类型相同。 (Massachusetts Institute of Technology)
创建与插入
使用 HashMap::new() 创建空 map;用 insert(key, value) 插入键值对。 (doc.rust-lang.org)
需要 use std::collections::HashMap;。没有像 vec! 的宏来快速初始化。 (Massachusetts Institute of Technology)
访问值
使用 get(&key) 方法获取 Option<&V>;若键不存在返回 None。也可遍历 map。 (doc.rust-lang.org)
若用 get, 得到的是 &V,如果需要值本身可能还要 copied()cloned()。 (doc.rust-lang.org)
所有权规则
插入 map 时:若键或值是拥有类型(如 String),它们会被 move;如果值实现 Copy(如 i32)则会被复制。 (Massachusetts Institute of Technology)
插入后原变量不能再使用(如果被 move 了)。
更新已有键
- 插入同一键会 覆盖 原值。 (doc.rust-lang.org) - 使用 entry(key).or_insert(value) 可以“仅当键不存在时插入”机制。 (doc.rust-lang.org) - 可通过 entry API 修改已有值,例如计数频次。 (doc.rust-lang.org)
推荐用 entry API 来处理“可能已存在的键”的逻辑。
注意事项/特性
- 遍历时键值对顺序不是固定的。 (doc.rust-lang.org) - 默认使用的 hashing 算法为 SipHash,兼顾安全但性能不是极致最快。 (doc.rust-lang.org)
如果性能关键,可自定义 hasher。
场景
示例代码
说明
创建 & 插入
rust<br>use std::collections::HashMap;<br><br>let mut scores = HashMap::new();<br>scores.insert(String::from("Blue"), 10);<br>scores.insert(String::from("Yellow"), 50);
创建空 map 并插入键值对。
访问值
rust<br>let team = String::from("Blue");<br>let score = scores.get(&team);<br>match score {<br> Some(s) => println!("分数: {}", s),<br> None => println!("没有找到"),<br>}
get() 返回 Option<&V>,需匹配处理。
遍历 HashMap
rust<br>for (key, value) in &scores {<br> println!("{}: {}", key, value);<br>}
遍历键值对,顺序不固定。
键值被移动
rust<br>let field = String::from("Color");<br>let value = String::from("Blue");<br>map.insert(field, value);<br>// field 和 value 在此之后不能再使用
插入时 String 被 move,若想保留原变量,可用 clone()
更新值(直接覆盖)
rust<br>scores.insert(String::from("Blue"), 25);
已存在键则覆盖旧值。
仅当不存在时插入
rust<br>scores.entry(String::from("Blue")).or_insert(50);
entry().or_insert() 若键存在返回可变引用,不存在则插入。
统计出现次数(经典用法)
rust<br>let text = "hello world wonderful world";<br>let mut map = HashMap::new();<br><br>for word in text.split_whitespace() {<br> let count = map.entry(word).or_insert(0);<br> *count += 1;<br>}<br>println!("{:?}", map);
entry API 非常适合计数、聚合等场景。
 
《Rust 程序设计语言》(9/22)《Rust 程序设计语言》(7/22)
Loading...