动态数组 Vector
Rust语言中的动态数组或者说可变数组,对应的是Vec<T>类型,动态数组只能存储相同类型的元素。这种类型在Rust中被广泛使用,允许我们在运行时动态地添加和删除元素。
Vec<T>在Rust中是一个堆分配的,动态大小的数组。它的内部实现是一个环形缓冲区,当达到容量限制时,它会自动进行重新分配,增长到更大的内存区域。
创建 Vec
Vec::new(): 创建一个空的Vec<T>。
let mut vec = Vec::new(); // 创建一个空的Vec
如果预先知道要存储的元素个数,可以使用
Vec::with_capacity(capacity)创建动态数组,这样可以避免因为插入大量新数据导致频繁的内存分配和拷贝,提升性能。
vec![]
还可以使用宏 vec! 来创建数组,与 Vec::new 有所不同,这个能在创建同时给予初始化值:
let v = vec![1, 2, 3];
处的 v 也无需标注类型,编译器只需检查它内部的元素即可自动推导出 v 的类型是 Vec<i32> (Rust 中,整数默认类型是 i32)。
添加元素
push(): 添加元素到Vec<T>中。
let mut vec = Vec::new();
vec.push(1); // 添加一个元素到Vec中
vec.push(2);
vec.push(3);
insert(): 在指定位置插入一个元素。
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
vec.insert(1, 10); // 在索引为1的位置插入元素10
println!("{:?}", vec); //[1, 10, 2]
删除元素
remove(): 删除Vec<T>中的元素。该方法会返回被删除的元素。
let mut vec = vec![1, 2, 3];
let num = vec.remove(1); // 删除索引为1的元素,保存到num中
swap_remove(): 删除并返回指定索引的元素,同时将该索引的元素与最后一个元素交换位置。
let mut vec = vec![1, 2, 3];
let num = vec.swap_remove(1); // 删除并返回索引为1的元素,同时与最后一个元素交换位置,保存到num中
clear(): 清除Vector中的所有元素。
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
vec.push(3);
vec.clear(); // 清空vec
println!("{:?}", vec); // []
访问元素
你可以使用索引来访问Vec<T>中的元素。请注意Rust的索引是从0开始的。
let vec = vec![1, 2, 3];
let first_num = vec[0]; // 访问第一个元素,应为1
如果你希望访问最后一个元素,可以使用last()方法。
let vec = vec![1, 2, 3];
let last_num = vec.last(); // 获取最后一个元素,应为3
使用 get 方法
v.get 的使用方式非常安全,它在内部做了处理,有值的时候返回 Some(T),无值的时候返回 None,避免了数组越界导致的报错退出。
let v = vec![1, 2, 3, 4, 5];
let does_not_exist = &v[100]; //因为发生了数组越界访问,导致程序报错退出
let does_not_exist = v.get(100);
对 Vec 进行迭代
你可以通过迭代器来遍历Vec<T>中的所有元素。如下例:
let vec = vec![1, 2, 3];
for num in &vec {
println!("{}", num); // 在循环中打印每个元素
}
或者使用 iter_mut() 和 into_iter() 来遍历并可能修改元素:
let mut vec = vec![1, 2, 3];
for num in vec.iter_mut() {
*num += 1; // 修改每个元素的值
}
let vec = vec![2, 3, 4]; // Vec现在包含修改后的元素
其他
len(): 返回Vector中元素的数量。
let vec = Vec::new();
vec.push(1);
vec.push(2);
vec.push(3);
println!("Number of elements: {}", vec.len()); // Number of elements: 3
is_empty(): 检查Vector是否为空。
let vec = Vec::new();
if vec.is_empty() { // 如果vec为空,打印一条信息
println!("Vector is empty."); // Vector is empty.
} else { // 如果vec不为空,打印另一条信息
println!("Vector is not empty."); // Vector is not empty.
}
capacity(): 返回Vector的当前容量(即可以存储的元素数量)。
let mut vec = Vec::new();
vec.push(1); // 向vec中添加一个元素,容量增加到1(因为内部已经分配了一个空间)
println!("Current capacity: {}", vec.capacity()); // 输出:Current capacity: 1,因为内部已经分配了一个空间。
KV 存储 HashMap
Rust语言中的 KV 存储 HashMap 对应的是 std::collections::HashMap。这是一个强大的数据结构,允许你存储键值对,其中键是唯一的。你可以使用这个数据结构来存储和管理各种类型的数据。
HashMap 在Rust中是用于存储键值对的数据结构,类似于其他编程语言中的哈希表或字典。它提供了存储,查找,删除等操作。
创建 HashMap
- 使用 new 方法创建
创建和插入一个HashMap的示例:
use std::collections::HashMap;
fn main() {
// 创建一个新的HashMap
let mut map = HashMap::new();
// 插入键值对
map.insert(String::from("key1"), String::from("value1"));
map.insert(String::from("key2"), String::from("value2"));
map.insert(String::from("key3"), String::from("value3"));
// 打印出所有的键值对
for (key, value) in &map {
println!("{}: {}", key, value);
}
}
在上述代码中,首先导入了
std::collections::HashMap,然后在main函数中创建了一个新的HashMap。然后,我们使用insert方法向哈希表中插入键值对。在循环中,我们遍历了HashMap中的所有键值对,并打印了它们。
跟
Vec一样,如果预先知道要存储的KV对个数,可以使用HashMap::with_capacity(capacity)创建指定大小的HashMap,避免频繁的内存分配和拷贝,提升性能。
- 使用迭代器和 collect 方法创建
在Rust中,你可以使用迭代器(Iterator)和collect方法来创建一个HashMap,而不使用for循环。以下是示例代码,展示了如何将Vec<(String, u32)>中的数据快速写入到HashMap<String, u32>中:
use std::collections::HashMap;
fn main() {
let data: Vec<(String, u32)> = vec![
("key1".to_string(), 1),
("key2".to_string(), 2),
("key3".to_string(), 3),
];
// 使用迭代器和collect方法创建HashMap
let hashmap: HashMap<_,_> = data.into_iter().collect();
// 打印HashMap中的值
println!("{:?}", hashmap); // {"key3": 3, "key2": 2, "key1": 1}
}
在这个示例中,首先创建了一个包含键值对的
Vec,然后通过调用into_iter方法将列表转为迭代器。
通过使用collect方法,我们可以将迭代器中的元素收集到一个新的HashMap中。最后,我们打印出HashMap中的值。
HashMap<_,_>的KV类型,会由编译器帮我们推导出HashMap<String, u32>。
- 有则更新,无则插入新值
use std::collections::HashMap;
fn main() {
let text = "a b c a";
let mut map = HashMap::new();
// 根据空格来切分字符串
for word in text.split_whitespace() {
let count = map.entry(word).or_insert(0);
*count += 1;
}
println!("{:?}", map); // {"c": 1, "a": 2, "b": 1}
}
在这个示例中,新建一个
map用于保存词语出现的次数,插入一个词语时会进行判断:若之前没有插入过,则使用该词语作Key,插入次数 0 作为Value,若之前插入过则取出之前统计的该词语出现的次数,对其加一。
注意:
or_insert返回了&mut v引用,因此可以通过该可变引用直接修改map中对应的值- 使用
count引用时,需要先进行解引用*count,否则会出现类型不匹配
- HashMap也提供了其他的方法,例如:
get(key: K) -> Option<&V>:获取一个键对应的值。- 如果这个键不存在,返回
None。否则,返回一个指向值的引用。 &V是对HashMap中值的借用,如果不使用借用,可能会发生所有权的转移
- 如果这个键不存在,返回
remove(key: K) -> Option<V>:删除一个键值对并返回它的值。如果这个键不存在,返回None。