Rust 向量(Vec)
Rust 向量是一个长度可变的数组,它使用一段 连续的内存块 存储相同类型的元素。
Rust 向量与数组不同之处在于:向量的长度是可变的,可以在运行时增长或者缩短,而数组的长度是固定不变的。
Rust 向量以特定顺序(添加顺序)将数据存储为元素序列。
向量中的每个元素都分配有唯一的索引号。
索引从 0 开始并自增到 n-1,其中 n 是集合的大小。
例如集合有 5 个元素,那么第一个元素的下标是 0,最后一个元素的下标是 4。
- 元素添加到向量时会添加到向量的末尾。这个操作类似于 栈 ( stack ),因此可以用来实现 栈 的功能。
- 向量的内存在 堆 ( heap ) 上存储,因此长度动态可变。
1. Rust 创建向量的语法
Rust 在标准库中定义了结构体 Vec 用于表示一个向量。同时提供了 new() 静态方法用于创建一个结构体 Vec 的实例。
向量的创建语法格式如下:
let mut instance_name = Vec::new();
除了提供 new() 静态方法创建向量之外, Rust 标准库还提供了 vec!() 宏来简化向量的创建。
let vector_name = vec![val1,val2,val3]
结构体 Vec 包含了大量的方法用于操作向量和向量中的元素,我们逻辑几个常见的于下表,并在后面做一个简单的介绍。
方法 | 签名 | 说明 |
---|---|---|
new() | pub fn new()->Vec | 创建一个空的向量的实例 |
push() | pub fn push(&mut self, value: T) | 将某个值 T 添加到向量的末尾 |
remove() | pub fn remove(&mut self, index: usize) -> T | 删除并返回指定的下标元素。 |
contains() | pub fn contains(&self, x: &T) -> bool | 判断向量是否包含某个值 |
len() | pub fn len(&self) -> usize | 返回向量中的元素个数 |
2. 使用 Vec::new() 静态方法创建向量
创建向量的一般通过调用 Vec 结构的 new() 静态方法来创建。
当有了向量的一个实例后,再通过 push() 方法像向量添加元素
fn main() { let mut v = Vec::new(); v.push(20); v.push(30); v.push(40); println!("size of vector is :{}",v.len()); println!("{:?}",v); }
运行以上 Rust 代码,输出结果如下
size of vector is :3 [20, 30, 40]
上面的代码中,我们使用结构体 Vec 提供的静态方法 new() 创建向量的一个实例。
有了向量时候之后,使用 push(val) 方法像实例添加元素。
len() 方法用于获取向量的元素个数。
3. 使用 vec! 宏创建向量
使用 Vec::new() 方法创建一个向量的实例,然后在使用 push() 方法添加元素的操作看起来有点复杂。
为了使创建向量看起来像创建数组那么简单,Rust 标准库提供了 vect! 用于简化向量的创建。
使用 vect! 宏创建向量时,向量的数据类型由第一个元素自动推断出来。
fn main() { let v = vec![1,2,3]; println!("{:?}",v); }
运行以上 Rust 代码,输出结果如下
[1, 2, 3]
向量也是相同类型元素的集合。
因此,如果给向量传递了不同数据类型的值则会引发错误 error[E0308]: mismatched types 。
下面的代码,编译会报错
fn main() { let v = vec![1,2,3,"hello"]; println!("{:?}",v); }
错误信息为
error[E0308]: mismatched types --> src/main.rs:2:23 | 2 | let v = vec![1,2,3,"hello"]; | ^^^^^^^ expected integer, found reference | = note: expected type `{integer}` found type `&'static str` error: aborting due to previous error
4. 追加元素到向量中 push()
push() 方法可以将指定的值添加到向量的末尾
fn main() { let mut v = Vec::new(); v.push(20); v.push(30); v.push(40); println!("{:?}",v); }
运行以上 Rust 代码,输出结果如下
[20, 30, 40]
5. 删除向量中的某个元素 remove()
remove() 方法移除并返回向量中指定的下标索引处的元素,将其后面的所有元素移到向左移动一位。
fn main() { let mut v = vec![10,20,30]; v.remove(1); println!("{:?}",v); }
运行以上 Rust 代码,输出结果如下
[10, 30]
6. 判断向量是否包含某个元素
contains() 用于判断向量是否包含某个值。
如果值在向量中存在则返回 true,否则返回 false。
fn main() { let v = vec![10,20,30]; if v.contains(&10) { println!("found 10"); } println!("{:?}",v); }
运行以上 Rust 代码,输出结果如下
found 10 [10, 20, 30]
7. 获取向量的长度
len() 方法可以获取向量的长度,也就是向量元素的个数。
fn main() { let v = vec![1,2,3]; println!("size of vector is :{}",v.len()); }
运行以上 Rust 代码,输出结果如下
size of vector is :3
8. 访问向量元素的方法
向量既然被称为是可变的数组,那么它的元素当然可以使用 下标 语法来访问。
也就是可以使用 索引号 来访问向量的每一个元素。
例如下面的代码,我们可以使用 v[0] 来访问第一个元素 20,使用 v[1] 来访问第二个元素。
fn main() { let mut v = Vec::new(); v.push(20); v.push(30); println!("{:?}",v[0]); }
运行以上 Rust 代码,输出结果如下
20
9. 迭代/遍历向量
向量本身就实现了迭代器特质,因此可以直接使用 for in 语法来遍历向量
fn main() { let mut v = Vec::new(); v.push(20); v.push(30); v.push(40); v.push(500); for i in v { println!("{}",i); } // println!("{:?}",v); // 运行出错,因为向量已经不可用 }
编译运行以上 Rust 代码,输出结果如下
20 30 40 500
如果把上面代码中的注释去掉,则会报编译错误
fn main() { let mut v = Vec::new(); v.push(20); v.push(30); v.push(40); v.push(500); for i in v { println!("{}",i); } println!("{:?}",v); // 运行出错,因为向量已经不可用 }
编译出错
error[E0382]: borrow of moved value: `v` --> src/main.rs:12:20 | 2 | let mut v = Vec::new(); | ----- move occurs because `v` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait ... 8 | for i in v { | - value moved here ... 12 | println!("{:?}",v); // 运行出错,因为向量已经不可用 | ^ value borrowed here after move
出错原因我们在 Rust 所有权 Ownership 章节已经提到过了,这里就不做详细介绍了。
修复的方式,就是在使用使用 for in 来迭代向量的一个引用
fn main() { let mut v = Vec::new(); v.push(20); v.push(30); v.push(40); v.push(500); for i in &v { println!("{}",i); } println!("{:?}",v); }
编译运行以上 Rust 代码,输出结果如下
20 30 40 500 [20, 30, 40, 500]
下一章:Rust 哈希表
Rust 哈希表(HashMap):哈希表 HashMap 就是键值对的集合。哈希表中不允许有重复的键,但允许不同的键有相同的值。哈希表 HashMap 常用于通过键查找对应的值。Rust 语言使用 HashMap 结构体来表示哈希表。HashMap 结构体在 Rust 语言标准库中的 std::collections 模块中定义。使用 HashMap 结构体之前需要显式导入 std::collections 模块。