向量(vector)
本质是可变数组
- 是一个
struct,定义在标准库中 vector只能储存相同类型的值- 和数组一样,是整体所有权
- 当
vector离开作用域时,其中的所有元素都会被释放
rust
pub struct Vec<T> {
ptr: Unique<T>, // 指向堆内存的原始指针
cap: usize, // 容量
len: usize, // 当前长度
}新建 vector
rust
// Vec::new 函数
let v: Vec<i32> = Vec::new(); // 空向量
// Vec::from 函数
let v: Vec<i32> = Vec::from([1, 2, 3]);
// vec! 宏
let v = vec![1, 2, 3];
Vec::new()需要显式类型标注;Vec::from函数和vec!宏可自动推导类型
增加元素
- 使用
push()方法添加元素到末尾
rust
let mut v = vec![1, 2, 3, 4, 5]; // 必须声明 mut
v.push(6);
push()方法会获得 vector 的可变引用,vector 必须声明为mut
读取元素
- 使用
[]直接索引读取元素 - 使用
get()方法读取元素
区别:
[]越界会 panic;get()越界返回None
rust
let v = vec![1, 2, 3, 4, 5];
// 使用索引 []
let third: &i32 = &v[2];
println!("The third element is {third}");
// 使用 get() 方法,返回 Option<&T>
let third: Option<&i32> = v.get(2);
match third {
Some(third) => println!("The third element is {third}"),
None => println!("There is no third element."),
}
get()不会获得所有权,只返回不可变引用
遍历 vector 中的元素
- 使用
for循环遍历不可变引用
rust
let v = vec![100, 32, 57];
// 遍历不可变引用
for i in &v {
println!("{i}");
}- 使用
for循环遍历可变引用修改元素
rust
let mut v = vec![100, 32, 57];
// 遍历可变引用,修改元素
for i in &mut v {
*i += 50;
}- 使用迭代器方法进行功能式编程
rust
let v = vec![100, 32, 57];
// 使用迭代器方法(获得所有权,v 被移动)
for i in v {
println!("{i}");
}遍历时使用
&v借用不可变引用;使用&mut v借用可变引用;直接使用v会获得所有权
使用枚举来储存多种类型
- vector 只能储存相同类型的值
- 枚举本身就是一个类型,可以在 vector 中储存多种类型的数据
rust
enum SpreadsheetCell {
Int(i32),
Float(f64),
Text(String),
}
let row = vec![
SpreadsheetCell::Int(3),
SpreadsheetCell::Text(String::from("blue")),
SpreadsheetCell::Float(10.12),
];
// 遍历枚举 vector
for cell in &row {
match cell {
SpreadsheetCell::Int(i) => println!("Int: {i}"),
SpreadsheetCell::Float(f) => println!("Float: {f}"),
SpreadsheetCell::Text(s) => println!("Text: {s}"),
}
}vector 本身类型统一为
Vec<SpreadsheetCell>;访问具体值时需用match或if let模式匹配
常用方法
增删方法
rust
let mut v = vec![3, 1, 4, 1, 5, 9];
v.pop(); // 移除并返回最后一个元素 → Option<T>(获得所有权)
v.remove(0); // 移除索引 0 的元素(后续元素左移),返回该元素(获得所有权)
v.insert(1, 10); // 在索引 1 处插入 10(原有元素右移)
v.drain(0..2); // 移除索引 0..2 的元素,返回被移除元素的迭代器(获得所有权)
v.retain(|x| *x > 2); // 只保留满足条件的元素(原地过滤)
v.dedup(); // 去除相邻重复元素(配合 sort 可实现完全去重)
v.clear(); // 清空向量查询方法
rust
let v = vec![1, 2, 3, 4, 5];
v.len(); // 返回元素个数 → usize
v.is_empty(); // 返回是否为空 → bool
v.contains(&3); // 返回是否包含某值 → bool(借用不可变引用)
v.iter().position(|x| *x == 3); // 返回首个满足条件的索引 → Option<usize>(借用不可变引用)
v.first(); // 返回首个元素 → Option<&T>(借用不可变引用)
v.last(); // 返回最后一个元素 → Option<&T>(借用不可变引用)排序
rust
let mut v = vec![3, 1, 4, 1, 5];
v.sort(); // 对实现了 Ord 的类型排序(整数、字符串等)
v.sort_by(|a, b| b.cmp(a)); // 自定义排序(这里是降序)
v.sort_by_key(|k| std::cmp::Reverse(*k)); // 按 key 排序
let mut floats = vec![3.1f64, 1.4, 2.7];
floats.sort_by(|a, b| a.partial_cmp(b).unwrap()); // f64 没实现 Ord,需用 partial_cmp合并与扩展
rust
let mut a = vec![1, 2, 3];
let b = vec![4, 5, 6];
a.extend(b.iter()); // 追加 b 的元素到 a(借用 b 的不可变引用)
a.extend([7, 8, 9]); // 追加数组
a.append(&mut b); // 将 b 的所有元素移动到 a,b 变为空向量(获得 b 的可变引用)容量与预分配
rust
// Vec::with_capacity 预先分配空间,避免频繁扩容,适合已知元素数量时
let mut v: Vec<i32> = Vec::with_capacity(100);
v.push(1);
println!("len={}, capacity={}", v.len(), v.capacity()); // len=1, capacity=100
v.shrink_to_fit(); // 释放多余容量,仅保留必需空间