Skip to content

Rust - 集合

Rust 的标准库(std::collections)提供了一套强大、高效且安全的集合类型,用于管理数据组。我们将探讨三个最核心的集合:Vec<T>(向量)、HashMap<K, V>(哈希映射)和 HashSet<T>(哈希集合)。

Vec<T>(发音为“vector”,即向量)是一个可增长的、同类型 T 值的列表,它们在内存中连续存储。它是 Rust 中使用最广泛的数据结构之一。

  • 同质: 所有元素必须是相同类型。
  • 堆分配: 数据存储在堆上,允许其在运行时增长或缩小。
  • 有序: 元素保持特定顺序,并通过从 0 开始的索引访问。
fn main() {
// 创建一个空向量并添加元素
let mut numbers: Vec<i32> = Vec::new();
numbers.push(10);
numbers.push(20);
numbers.push(30);
// 使用 vec! 宏创建带有初始值的向量
let mut fruits = vec!["Apple", "Banana", "Cherry"];
println!("Initial fruits: {:?}", fruits);
// 访问元素
// 使用 .get() 更安全,因为它返回 Option<&T>
match fruits.get(1) {
Some(fruit) => println!("The second fruit is: {}", fruit),
None => println!("There is no second fruit."),
}
// 如果索引超出范围,直接索引将导致 panic
let first_fruit = &fruits[0];
println!("The first fruit is: {}", first_fruit);
// 迭代和修改
for fruit in &mut fruits {
*fruit = "Juicy Fruit"; // 通过可变引用修改每个元素
}
println!("Modified fruits: {:?}", fruits);
}
方法描述
Vec::new()创建一个新的空向量。
vec![...]一个方便的宏,用于创建带有初始元素的向量。
push(value)将一个元素添加到向量的末尾。
pop()移除并返回最后一个元素,以 Option<T> 形式。
len()返回向量中的元素数量。
get(index)返回 index 处元素的 Option<&T>。安全。
[index]返回 index 处元素的引用。如果超出边界则会导致 panic。

一个 HashMap<K, V> 存储了类型 K 的键到类型 V 的值的映射。它使用哈希函数(hashing function)来确定如何存储和检索数据,使得查找、插入和删除操作在平均情况下极快。键必须是唯一的。

use std::collections::HashMap;
fn main() {
// 创建一个新的 HashMap
let mut scores = HashMap::new();
// 插入键值对
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
// 使用键访问值
let team_name = String::from("Blue");
let score = scores.get(&team_name).copied().unwrap_or(0);
println!("The score for Blue team is: {}", score);
// 遍历键值对
for (key, value) in &scores {
println!("{}: {}", key, value);
}
}

entry API 是处理复杂逻辑的惯用方式,例如仅在键不存在时插入值,或更新现有值。

use std::collections::HashMap;
fn main() {
let text = "hello world wonderful world";
let mut map = HashMap::new();
for word in text.split_whitespace() {
// .entry() 返回一个表示潜在条目的枚举(Enum)
// .or_insert(0) 获取值,如果不存在则插入 0
let count = map.entry(word).or_insert(0);
*count += 1; // 递增计数
}
println!("Word counts: {:?}", map);
}

一个 HashSet<T> 是一个集合,其中每个元素都是唯一的。它作为 HashMap<T, ()> 的一个包装器实现,并且在检查集合中是否存在某个值时速度极快。

use std::collections::HashSet;
fn main() {
let mut visited_cities = HashSet::new();
// insert() 如果值是新插入的,则返回 true
assert!(visited_cities.insert("Tokyo"));
assert!(visited_cities.insert("London"));
// 插入重复值返回 false
assert!(!visited_cities.insert("Tokyo"));
println!("Visited cities: {:?}", visited_cities);
// 检查是否存在
if visited_cities.contains("London") {
println!("We have been to London!");
}
}

HashSet 还支持强大的数学集合操作。

use std::collections::HashSet;
fn main() {
let set1: HashSet<_> = [1, 2, 3].iter().cloned().collect();
let set2: HashSet<_> = [2, 3, 4].iter().cloned().collect();
// 并集:任一集合中的元素
println!("Union: {:?}", set1.union(&set2).collect::<Vec<_>>());
// 交集:两个集合中都存在的元素
println!("Intersection: {:?}", set1.intersection(&set2).collect::<Vec<_>>());
// 差集:在 set1 中但不在 set2 中的元素
println!("Difference: {:?}", set1.difference(&set2).collect::<Vec<_>>());
}
  • 当你需要一个有序的元素序列时,使用 Vec<T>。
  • 当你需要将值与唯一键关联以进行快速查找时,使用 HashMap<K, V>。
  • 当你只需要存储唯一值并快速检查它们是否存在时,使用 HashSet<T>。