我來詳細(xì)介紹 Rust 中 HashMap 的使用方法。
HashMap 基礎(chǔ)用法
1. 引入和創(chuàng)建
use std::collections::HashMap;
fn main() {
// 方法1: 創(chuàng)建空的 HashMap
let mut map: HashMap<String, i32> = HashMap::new();
// 方法2: 使用 with_capacity 預(yù)分配容量
let mut map2: HashMap<String, i32> = HashMap::with_capacity(10);
// 方法3: 從迭代器創(chuàng)建
let map3: HashMap<&str, i32> = [("a", 1), ("b", 2), ("c", 3)]
.iter()
.cloned()
.collect();
// 方法4: 使用 HashMap::from (Rust 1.56+)
let map4 = HashMap::from([
("apple", 3),
("banana", 2),
("orange", 5),
]);
}
2. 插入和訪問
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
// 插入鍵值對(duì)
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
// 訪問值
let team_name = String::from("Blue");
// 方法1: get() 返回 Option<&V>
match scores.get(&team_name) {
Some(score) => println!("Blue team score: {}", score),
None => println!("Team not found"),
}
// 方法2: 使用 unwrap_or 提供默認(rèn)值
let score = scores.get(&team_name).unwrap_or(&0);
println!("Score: {}", score);
// 方法3: 使用索引訪問 (會(huì) panic 如果鍵不存在)
// let score = &scores[&team_name]; // 謹(jǐn)慎使用
}
3. 更新值的不同方式
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
// 1. 直接覆蓋
map.insert("key1", 10);
map.insert("key1", 20); // 覆蓋之前的值
// 2. 只在鍵不存在時(shí)插入
map.entry("key2").or_insert(30);
map.entry("key2").or_insert(40); // 不會(huì)覆蓋,key2 仍然是 30
// 3. 基于現(xiàn)有值更新
let count = map.entry("key3").or_insert(0);
*count += 1; // 增加計(jì)數(shù)
// 4. 復(fù)雜的更新邏輯
map.entry("key4")
.and_modify(|v| *v += 10) // 如果存在,加10
.or_insert(5); // 如果不存在,插入5
println!("{:?}", map);
}
4. 遍歷 HashMap
use std::collections::HashMap;
fn main() {
let mut map = HashMap::from([
("apple", 3),
("banana", 2),
("orange", 5),
]);
// 1. 遍歷鍵值對(duì)
for (key, value) in &map {
println!("{}: {}", key, value);
}
// 2. 只遍歷鍵
for key in map.keys() {
println!("Key: {}", key);
}
// 3. 只遍歷值
for value in map.values() {
println!("Value: {}", value);
}
// 4. 可變遍歷值
for value in map.values_mut() {
*value += 1; // 所有值加1
}
// 5. 遍歷并獲取所有權(quán)
for (key, value) in map {
println!("Owned: {} = {}", key, value);
}
// 注意:map 在這里被移動(dòng)了,后面不能再使用
}
5. 常用方法
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("a", 1);
map.insert("b", 2);
map.insert("c", 3);
// 檢查是否包含鍵
if map.contains_key("a") {
println!("包含鍵 'a'");
}
// 獲取長度
println!("HashMap 長度: {}", map.len());
// 檢查是否為空
if !map.is_empty() {
println!("HashMap 不為空");
}
// 移除鍵值對(duì)
if let Some(value) = map.remove("b") {
println!("移除了 'b': {}", value);
}
// 清空 HashMap
map.clear();
println!("清空后長度: {}", map.len());
// 容量相關(guān)
map.reserve(100); // 預(yù)留容量
println!("容量: {}", map.capacity());
map.shrink_to_fit(); // 縮減到合適大小
}
6. 處理復(fù)雜數(shù)據(jù)類型
use std::collections::HashMap;
#[derive(Debug)]
struct Student {
name: String,
age: u32,
grade: f64,
}
fn main() {
// HashMap 存儲(chǔ)結(jié)構(gòu)體
let mut students: HashMap<u32, Student> = HashMap::new();
students.insert(1, Student {
name: String::from("Alice"),
age: 20,
grade: 85.5,
});
students.insert(2, Student {
name: String::from("Bob"),
age: 19,
grade: 92.0,
});
// 訪問結(jié)構(gòu)體字段
if let Some(student) = students.get(&1) {
println!("學(xué)生姓名: {}", student.name);
}
// HashMap 存儲(chǔ) Vec
let mut groups: HashMap<String, Vec<String>> = HashMap::new();
groups.entry(String::from("Math")).or_insert(Vec::new())
.push(String::from("Alice"));
groups.entry(String::from("Math")).or_insert(Vec::new())
.push(String::from("Bob"));
println!("{:?}", groups);
}
7. 字符串作為鍵的注意事項(xiàng)
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
// 使用 String 作為鍵
let key = String::from("hello");
map.insert(key, 42);
// println!("{}", key); // 錯(cuò)誤!key 已經(jīng)被移動(dòng)
// 解決方案1: 克隆鍵
let key2 = String::from("world");
map.insert(key2.clone(), 24);
println!("還可以使用 key2: {}", key2);
// 解決方案2: 使用 &str 作為鍵類型
let mut map2: HashMap<&str, i32> = HashMap::new();
let text = "hello";
map2.insert(text, 42);
println!("還可以使用 text: {}", text);
// 解決方案3: 使用引用插入(需要生命周期管理)
let mut map3 = HashMap::new();
let key3 = String::from("test");
map3.insert(&key3, 42); // 插入引用
println!("還可以使用 key3: {}", key3);
}
8. 實(shí)際應(yīng)用示例
use std::collections::HashMap;
// 計(jì)算單詞頻率
fn word_count(text: &str) -> HashMap<&str, usize> {
let mut counts = HashMap::new();
for word in text.split_whitespace() {
let count = counts.entry(word).or_insert(0);
*count += 1;
}
counts
}
// 分組操作
fn group_by_length(words: Vec<&str>) -> HashMap<usize, Vec<&str>> {
let mut groups = HashMap::new();
for word in words {
groups.entry(word.len())
.or_insert(Vec::new())
.push(word);
}
groups
}
fn main() {
// 單詞計(jì)數(shù)
let text = "hello world hello rust world";
let counts = word_count(text);
for (word, count) in counts {
println!("{}: {}", word, count);
}
// 按長度分組
let words = vec!["cat", "dog", "elephant", "ant", "bear"];
let groups = group_by_length(words);
for (length, words) in groups {
println!("長度 {}: {:?}", length, words);
}
}
9. 性能提示
use std::collections::HashMap;
fn main() {
// 1. 預(yù)分配容量以避免重新分配
let mut map = HashMap::with_capacity(1000);
// 2. 使用 entry API 避免重復(fù)查找
// 好的做法
*map.entry("key").or_insert(0) += 1;
// 不好的做法(兩次查找)
if map.contains_key("key") {
let count = map.get_mut("key").unwrap();
*count += 1;
} else {
map.insert("key", 1);
}
// 3. 批量操作
let data = vec![("a", 1), ("b", 2), ("c", 3)];
let map2: HashMap<_, _> = data.into_iter().collect();
}
這就是 Rust HashMap 的全面使用指南!HashMap 是處理鍵值對(duì)數(shù)據(jù)的強(qiáng)大工具,掌握這些用法可以讓你的 Rust 代碼更加高效。