开始
本章节介绍 rust 中的三个常用集合
- vector
- String
- HashMap
三种集合在内存分配上遵循相同的模式,即在栈上保存一个固定大小的结构体,其中包含一个指向存储元素的堆内存的指针,直接赋值时发生所有权移动
vector
Vector 表示一个长度可变的数组,是一个类型为 Vec<T>
的结构体
创建 vector
使用 new()
关联函数创建一个空的 vector
1 | let v: Vec<i32> = Vec::new(); |
使用初始值创建 vector 时,使用 vec!
宏,支持类型推断
1 | let v = vec![1, 2, 3]; |
访问 vector
有两种方式可以访问 vector 元素
-
索引访问:索引越界时会抛出 panic
1
2
3
4
5
6
7let v = vec![1, 2, 3];
let a: i32 = v[0]; // 发生数据移动或拷贝
let b: &i32 = &v[0]; // 获取元素的不可变引用,遵循借用期规则
let s: &[i32] = &v[0..2]; // slice引用
let mut v1 = vec![1, 2, 3];
let c: &mut i32 = &mut v1[0]; // 获取元素的可变引用,遵循借用期规则注意,访问时应该使用引用,直接访问会发生数据的移动或拷贝
-
get
方法:返回Option<T>
,数组越界时返回None
1
2
3
4
5
6let v = vec![1, 2, 3];
let a = v.get(0);
match a {
Some(n) => {}
None => {}
}
更新 vector
使用更新 vector 的方法时,会隐式传入 vector 的可变引用,因此需要声明变量为可变的
-
添加元素
1
2let mut v = vec![1, 2, 3];
v.push(1); // 添加元素 -
修改元素
1
2
3
4
5
6let mut v = vec![1, 2, 3];
v[0] = 1;
// 通过引用修改
let a: &mut i32 = &mut v[0]; // 获取可变引用
*a = 2; // 解引用后获取引用的值,可访问或修改 -
删除元素
1
2let mut v = vec![1, 2, 3];
let removed = v.remove(0); // 移除第一个元素并返回它
遍历 vector
不可变引用遍历
1 | let v = vec![100, 32, 57]; |
可变引用遍历
1 | let mut v = vec![100, 32, 57]; |
String
创建字符串
1 | let empty = String::new(); // 创建一个空字符串 |
添加字符串
1 | let s = String::new(); |
拼接字符串
1 | // 使用+运算符拼接两个字符串 |
注意,使用
+
运算符实际是调用了add
方法,它的函数签名为fn add(self, s: &str) -> String
,左操作数传入值,会发生所有权移动,右操作数传入&str
引用,可以接收 String 引用和字符串字面量
{: .prompt-info}
遍历字符串
由于 rust 内对于存储的字符串字节支持多种方式来解释(字节、Unicode 标量值等),因此字符串不支持索引访问
遍历字符串需要使用字符数组或字节数组的迭代器访问
1 | // 字符数组迭代器 |
HashMap
使用 HashMap 需要从模块中引入
1 | use std::collections::HashMap; |
创建 HashMap
1 | use std::collections::HashMap; |
插入键值对
1 | let mut map = HashMap::new(); // 可根据插入数据推断类型 |
注意,若在插入时传入变量,则会发生数据的移动或拷贝
1 | let mut map = HashMap::new(); |
访问 HashMap
1 | let mut map = HashMap::new(); |
遍历 HashMap
1 | // 通过不可变引用遍历 |
更新 HashMap
-
覆盖旧值
当多次对同一个键调用
insert
方法时,新值会覆盖旧值 -
缺失值插入
使用
entry
方法获取键值对,返回Entry<K, V>
枚举,其中包含Occupied
和Vacant
两种状态Entry
中包含许多原地操作方法,如and_modify
和or_insert
等1
2
3
4let mut map = HashMap::new();
map.insert(String::from("a"), 1);
// 获取键值对后,若为Occupied,返回value可变引用,若为Vacant,则插入指定值,返回value可变引用
let value: &mut i32 = map.entry(String::from("b")).or_insert(1);