Rust HashMap
最后修改于 2025 年 2 月 19 日
在本文中,我们将展示如何在 Rust 中使用 HashMap。
HashMap 是键值对的集合,其中每个键都是唯一的。HashMap 通过键高效地存储和检索数据非常有用。
要在 Rust 中使用 HashMap,我们需要从 std::collections 模块导入 HashMap 类型。
Rust 创建 HashMap
在第一个示例中,我们在 Rust 中创建并初始化 HashMap。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
println!("{:?}", scores);
let teams = vec![String::from("Blue"), String::from("Yellow")];
let initial_scores = vec![10, 50];
let scores2: HashMap<_, _> = teams.into_iter().zip(initial_scores.into_iter()).collect();
println!("{:?}", scores2);
}
在示例中,我们创建了两个 HashMap。
let mut scores = HashMap::new();
我们使用 HashMap::new() 创建一个空的 HashMap。mut 关键字使 HashMap 可变,允许我们稍后添加键值对。
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
我们使用 insert 方法将键值对插入到 HashMap 中。
let scores2: HashMap<_, _> = teams.into_iter().zip(initial_scores.into_iter()).collect();
我们使用 zip 方法和 collect 从两个向量创建 HashMap。
λ cargo run -q
{"Blue": 10, "Yellow": 50}
{"Blue": 10, "Yellow": 50}
Rust 访问 HashMap 元素
我们可以使用 get 方法访问 HashMap 中的元素。
use std::collections::HashMap;
fn main() {
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);
match score {
Some(s) => println!("Score for {}: {}", team_name, s),
None => println!("Team {} not found", team_name),
}
}
在示例中,我们访问与键 "Blue" 关联的值。
let score = scores.get(&team_name);
get 方法返回一个 Option<&V>,如果键存在则为 Some,如果键不存在则为 None。
λ cargo run -q Score for Blue: 10
Rust 更新 HashMap
我们可以使用 insert 方法更新 HashMap 中的值。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
println!("Before update: {:?}", scores);
scores.insert(String::from("Blue"), 25);
println!("After update: {:?}", scores);
}
在示例中,我们更新了与键 "Blue" 关联的值。
λ cargo run -q
Before update: {"Blue": 10, "Yellow": 50}
After update: {"Blue": 25, "Yellow": 50}
使用 for 循环
我们可以使用 for 循环遍历 HashMap 中的键值对。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
for (key, value) in &scores {
println!("{}: {}", key, value);
}
}
在示例中,我们遍历 HashMap 并打印每个键值对。
λ cargo run -q Blue: 10 Yellow: 50
使用 while 循环
我们可以使用 while 循环遍历 HashMap 中的键值对。
use std::collections::HashMap;`
fn main() {
let mut fruits: HashMap<i32, String> = HashMap::new();
fruits.insert(1, String::from("Apple"));
fruits.insert(2, String::from("Banana"));
fruits.insert(3, String::from("Cherry"));
let mut iterator = fruits.iter(); // Obtain an iterator
while let Some((key, value)) = iterator.next() {
println!("Key: {}, Value: {}", key, value);
}
}
我们遍历 HashMap 并打印每个键值对。
let mut iterator = fruits.iter(); // Obtain an iterator
我们使用 fruits.iter 显式创建一个迭代器。
while let Some((key, value)) = iterator.next() {
println!("Key: {}, Value: {}", key, value);
}
只要迭代器产生一个 Some 值(即,还有更多元素),while let 循环就会继续。
iterator.next 将下一个键值对检索为 Option<(key, value)>。如果键值对存在,循环会解构它,打印键和值。
λ cargo run -q Key: 2, Value: Banana Key: 1, Value: Apple Key: 3, Value: Cherry
Rust HashMap 删除
我们可以使用 remove 方法从 HashMap 中删除键值对。此方法接受要从 HashMap 中删除的键的引用。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Red"), 20);
scores.insert(String::from("Green"), 40);
scores.insert(String::from("Blue"), 60);
println!("Before remove: {:?}", scores);
scores.remove(&String::from("Green"));
println!("After remove: {:?}", scores);
}
在此示例中,我们创建了一个名为 scores 的可变 HashMap 来存储团队名称及其分数。
scores.insert(String::from("Red"), 20);
scores.insert(String::from("Green"), 40);
scores.insert(String::from("Blue"), 60);
我们将三个键值对插入到 HashMap 中,分别代表三个团队:“Red” 分数 20,“Green” 分数 40,“Blue” 分数 60。
scores.remove(&String::from("Green"));
我们使用 remove 方法删除与键 "Green" 关联的键值对。remove 方法接受键的引用,这就是为什么我们使用 &String::from("Green")。
λ cargo run -q
Before remove: {"Red": 20, "Green": 40, "Blue": 60}
After remove: {"Red": 20, "Blue": 60}
Rust HashMap 键
我们可以使用 keys 方法迭代存储在 HashMap 中的键。此方法返回一个产生 HashMap 中每个键引用的迭代器。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Red"), 20);
scores.insert(String::from("Green"), 40);
scores.insert(String::from("Blue"), 60);
println!("HashMap: {:?}", scores);
println!("Keys:");
for team in scores.keys() {
println!("{}", team);
}
}
在此示例中,我们创建了一个名为 scores 的 HashMap 来存储团队名称及其分数。
scores.insert(String::from("Red"), 20);
scores.insert(String::from("Green"), 40);
scores.insert(String::from("Blue"), 60);
我们将三个键值对插入到 HashMap 中,分别代表三个团队:“Red” 分数 20,“Green” 分数 40,“Blue” 分数 60。
for team in scores.keys() {
println!("{}", team);
}
我们使用 keys 方法获取 HashMap 中键的迭代器。for 循环遍历每个键(团队名称)并将其打印到控制台。
λ cargo run -q
HashMap: {"Red": 20, "Green": 40, "Blue": 60}
Keys:
Red
Green
Blue
Rust HashMap 值
我们可以使用 values 方法迭代存储在 HashMap 中的值。此方法返回一个产生 HashMap 中每个值引用的迭代器。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Red"), 20);
scores.insert(String::from("Green"), 40);
scores.insert(String::from("Blue"), 60);
println!("HashMap: {:?}", scores);
println!("Values:");
for score in scores.values() {
println!("{}", score);
}
}
在此示例中,我们创建了一个名为 scores 的 HashMap 来存储团队名称及其分数。
scores.insert(String::from("Red"), 20);
scores.insert(String::from("Green"), 40);
scores.insert(String::from("Blue"), 60);
我们将三个键值对插入到 HashMap 中,分别代表三个团队:“Red” 分数 20,“Green” 分数 40,“Blue” 分数 60。
for score in scores.values() {
println!("{}", score);
}
我们使用 values 方法获取 HashMap 中值的迭代器。for 循环遍历每个值(分数)并将其打印到控制台。
λ cargo run -q
HashMap: {"Red": 20, "Green": 40, "Blue": 60}
Values:
20
40
60
Rust HashMap entry
entry 允许我们检查键是否存在,并在键不存在时插入一个值。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
scores.entry(String::from("Blue")).or_insert(25);
scores.entry(String::from("Red")).or_insert(100);
println!("{:?}", scores);
}
在示例中,我们使用 entry 方法仅在键不存在时插入值。
λ cargo run -q
{"Blue": 10, "Yellow": 50, "Red": 100}
Rust HashMap 计数元素
我们可以使用 len 方法计算 HashMap 中的键值对数量。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
println!("Number of elements: {}", scores.len());
}
在示例中,我们计算了 HashMap 中键值对的数量。
λ cargo run -q Number of elements: 2
Rust HashMap 检查键是否存在
我们可以使用 contains_key 方法检查 HashMap 中是否存在某个键。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
let team_name = String::from("Blue");
if scores.contains_key(&team_name) {
println!("{} exists in the HashMap", team_name);
} else {
println!("{} does not exist in the HashMap", team_name);
}
}
在示例中,我们检查 HashMap 中是否存在键 "Blue"。
λ cargo run -q Blue exists in the HashMap
Rust HashMap 合并
我们可以使用 extend 方法合并两个 HashMap。
use std::collections::HashMap;
fn main() {
let mut scores1 = HashMap::new();
scores1.insert(String::from("Blue"), 10);
scores1.insert(String::from("Yellow"), 50);
let mut scores2 = HashMap::new();
scores2.insert(String::from("Red"), 100);
scores2.insert(String::from("Green"), 75);
scores1.extend(scores2);
println!("{:?}", scores1);
}
在示例中,我们将两个 HashMap 合并为一个。
λ cargo run -q
{"Blue": 10, "Yellow": 50, "Red": 100, "Green": 75}
Rust HashMap 清空
我们可以使用 clear 方法从 HashMap 中清除所有键值对。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
println!("Before clear: {:?}", scores);
scores.clear();
println!("After clear: {:?}", scores);
}
在示例中,我们清除了 HashMap 中的所有键值对。
λ cargo run -q
Before clear: {"Blue": 10, "Yellow": 50}
After clear: {}
Rust HashMap 克隆
我们可以使用 clone 方法克隆一个 HashMap。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
let scores2 = scores.clone();
println!("Original: {:?}", scores);
println!("Clone: {:?}", scores2);
}
在示例中,我们克隆了一个 HashMap。
λ cargo run -q
Original: {"Blue": 10, "Yellow": 50}
Clone: {"Blue": 10, "Yellow": 50}
Rust HashMap 迭代和修改
我们可以迭代 HashMap 并修改其值。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
for (_, value) in &mut scores {
*value += 10;
}
println!("{:?}", scores);
}
在示例中,我们迭代 HashMap 并将每个值增加 10。
λ cargo run -q
{"Blue": 20, "Yellow": 60}
Rust HashMap 从迭代器创建
我们可以从键值对的迭代器创建 HashMap。
use std::collections::HashMap;
fn main() {
let teams = vec![String::from("Blue"), String::from("Yellow")];
let scores = vec![10, 50];
let scores_map: HashMap<_, _> = teams.into_iter().zip(scores.into_iter()).collect();
println!("{:?}", scores_map);
}
在示例中,我们使用 zip 方法从两个向量创建 HashMap。
λ cargo run -q
{"Blue": 10, "Yellow": 50}
Rust HashMap 过滤
我们可以使用 retain 方法过滤 HashMap。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
scores.insert(String::from("Red"), 100);
scores.retain(|_, &mut v| v > 20);
println!("{:?}", scores);
}
在示例中,我们过滤 HashMap,只保留值大于 20 的键值对。
λ cargo run -q
{"Yellow": 50, "Red": 100}
Rust HashMap 按键排序
我们可以使用 BTreeMap 类型按键对 HashMap 进行排序。
use std::collections::BTreeMap;
fn main() {
let mut scores = BTreeMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
scores.insert(String::from("Red"), 100);
println!("{:?}", scores);
}
在示例中,我们使用 BTreeMap 按键对 HashMap 进行排序。
λ cargo run -q
{"Blue": 10, "Red": 100, "Yellow": 50}
Rust HashMap 按值排序
我们可以通过将其转换为元组向量来按值对 HashMap 进行排序。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
scores.insert(String::from("Red"), 100);
let mut sorted_scores: Vec<_> = scores.into_iter().collect();
sorted_scores.sort_by(|a, b| a.1.cmp(&b.1));
println!("{:?}", sorted_scores);
}
在示例中,我们按值对 HashMap 进行排序。
let mut sorted_scores: Vec<_> = scores.into_iter().collect();
这会将 scores HashMap 转换为一个元组向量。每个元组包含一个键及其对应的值。into_iter 方法消耗 HashMap 并生成一个迭代器,collect 将迭代器的项收集到一个向量中。
sorted_scores.sort_by(|a, b| a.1.cmp(&b.1));
这会根据元组中的值对 sorted_scores 向量进行排序。sort_by smethod 接受一个闭包,该闭包使用 cmp 方法比较值(a.1 和 b.1)。
λ cargo run -q
[("Blue", 10), ("Yellow", 50), ("Red", 100)]
Rust HashMap 使用自定义键类型
通过实现 Eq 和 Hash trait,我们可以使用自定义类型作为 HashMap 的键。
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
#[derive(Eq, PartialEq)]
struct CustomKey {
id: u32,
name: String,
}
impl Hash for CustomKey {
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state);
self.name.hash(state);
}
}
fn main() {
let mut scores = HashMap::new();
let key1 = CustomKey { id: 1, name: String::from("Blue") };
let key2 = CustomKey { id: 2, name: String::from("Yellow") };
scores.insert(key1, 10);
scores.insert(key2, 50);
println!("{:?}", scores.get(&CustomKey { id: 1, name: String::from("Blue") }));
}
在示例中,我们使用自定义类型作为 HashMap 的键。
λ cargo run -q Some(10)
Rust HashMap 使用自定义值类型
我们可以在 HashMap 中使用自定义类型作为值。
use std::collections::HashMap;
#[derive(Debug)]
struct CustomValue {
score: u32,
description: String,
}
fn main() {
let mut scores = HashMap::new();
let value1 = CustomValue { score: 10, description: String::from("Good") };
let value2 = CustomValue { score: 50, description: String::from("Excellent") };
scores.insert(String::from("Blue"), value1);
scores.insert(String::from("Yellow"), value2);
println!("{:?}", scores.get(&String::from("Blue")));
}
在示例中,我们使用自定义类型作为 HashMap 的值。
λ cargo run -q
Some(CustomValue { score: 10, description: "Good" })
Rust HashMap 默认值
我们可以使用 entry 方法为 HashMap 提供默认值。当您想确保某个键始终具有值时,这特别有用,即使它之前没有被显式插入到 HashMap 中。让我们通过一个示例详细了解其工作原理。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
// Define a team name that doesn't exist in the HashMap
let team_name = String::from("Red");
let score = scores.entry(team_name.clone()).or_insert(0);
println!("{}: {}", team_name, score);
}
在此示例中,我们首先创建一个名为 scores 的可变 HashMap 来存储团队名称及其分数。接下来,我们定义一个当前不在 HashMap 中的团队名称 "Red"。我们使用 entry 来检查键 "Red" 是否存在于 HashMap 中。如果不存在,我们使用 or_insert 方法插入默认值 0。这确保了 HashMap 对于指定的键始终有一个值。
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
将一些键值对插入 HashMap。
最后,我们使用 println! 宏打印团队名称及其分数。由于 "Red" 最初不存在于 HashMap 中,因此插入了默认值 0,我们看到输出。
λ cargo run -q Red: 0
Rust HashMap 容量
我们可以使用 with_capacity 方法创建具有特定容量的 HashMap。
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::with_capacity(10);
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
println!("Capacity: {}", scores.capacity());
}
在示例中,我们创建了一个容量为 10 的 HashMap。
λ cargo run -q Capacity: 10
Rust HashMap 从数组创建
我们可以从元组数组创建 HashMap。
use std::collections::HashMap;
fn main() {
let scores: HashMap<_, _> = [
(String::from("Blue"), 10),
(String::from("Yellow"), 50),
].iter().cloned().collect();
println!("{:?}", scores);
}
在示例中,我们从元组数组创建了 HashMap。
λ cargo run -q
{"Blue": 10, "Yellow": 50}
Rust HashMap 从向量创建
我们可以从元组向量创建 HashMap。
use std::collections::HashMap;
fn main() {
let scores: HashMap<_, _> = vec![
(String::from("Blue"), 10),
(String::from("Yellow"), 50),
].into_iter().collect();
println!("{:?}", scores);
}
在示例中,我们从元组向量创建了 HashMap。
λ cargo run -q
{"Blue": 10, "Yellow": 50}
Rust HashMap 从迭代器创建
我们可以从键值对的迭代器创建 HashMap。
use std::collections::HashMap;
fn main() {
let teams = vec![String::from("Blue"), String::from("Yellow")];
let scores = vec![10, 50];
let scores_map: HashMap<_, _> = teams.into_iter().zip(scores.into_iter()).collect();
println!("{:?}", scores_map);
}
在示例中,我们从键值对的迭代器创建了 HashMap。
λ cargo run -q
{"Blue": 10, "Yellow": 50}
Rust HashMap 从切片创建
我们可以从元组切片创建 HashMap。
use std::collections::HashMap;
fn main() {
let scores: HashMap<_, _> = [
(String::from("Blue"), 10),
(String::from("Yellow"), 50),
].iter().cloned().collect();
println!("{:?}", scores);
}
在示例中,我们从元组切片创建了 HashMap。
λ cargo run -q
{"Blue": 10, "Yellow": 50}
Rust HashMap 从范围创建
我们可以从键值对的范围创建 HashMap。
use std::collections::HashMap;
fn main() {
let scores: HashMap<_, _> = (0..5).map(|i| (i, i * 10)).collect();
println!("{:?}", scores);
}
在示例中,我们从键值对的范围创建了 HashMap。
λ cargo run -q
{0: 0, 1: 10, 2: 20, 3: 30, 4: 40}
Rust HashMap 从元组迭代器创建
我们可以从元组的迭代器创建 HashMap。
use std::collections::HashMap;
fn main() {
let scores: HashMap<_, _> = [
(String::from("Blue"), 10),
(String::from("Yellow"), 50),
].iter().cloned().collect();
println!("{:?}", scores);
}
在示例中,我们从元组的迭代器创建了 HashMap。
λ cargo run -q
{"Blue": 10, "Yellow": 50}
Rust HashMap 从键值对迭代器创建
我们可以从键值对的迭代器创建 HashMap。
use std::collections::HashMap;
fn main() {
let teams = vec![String::from("Blue"), String::from("Yellow")];
let scores = vec![10, 50];
let scores_map: HashMap<_, _> = teams.into_iter().zip(scores.into_iter()).collect();
println!("{:?}", scores_map);
}
在示例中,我们从键值对的迭代器创建了 HashMap。
λ cargo run -q
{"Blue": 10, "Yellow": 50}
在本文中,我们学习了 Rust 中的变量。
作者
列出 所有 Rust 教程。