HashMap 哈希表
学习目标
- 创建和操作 HashMap
- 掌握所有权规则
- 掌握常用 API
- 理解 Entry API
核心概念
创建
use std::collections::HashMap;
fn main() {
let mut scores: HashMap<String, i32> = HashMap::new();
scores.insert(String::from("Alice"), 95);
scores.insert(String::from("Bob"), 87);
let pairs = [("Alice", 95), ("Bob", 87)];
let scores: HashMap<&str, i32> = pairs.into_iter().collect();
let keys = vec!["Alice", "Bob"];
let values = vec![95, 87];
let scores: HashMap<&str, i32> = keys.into_iter().zip(values).collect();
}
访问
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert("Alice", 95);
let alice = scores.get("Alice");
let unknown = scores.get("Unknown");
for (key, value) in &scores {
println!("{}: {}", key, value);
}
let has_alice = scores.contains_key("Alice");
println!("len: {}", scores.len());
println!("is_empty: {}", scores.is_empty());
}
更新
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("key", 1);
map.insert("key", 2);
map.entry("key").or_insert(3);
map.entry("new").or_insert(4);
let text = "hello world hello";
let mut word_count = HashMap::new();
for word in text.split_whitespace() {
let count = word_count.entry(word).or_insert(0);
*count += 1;
}
println!("{:?}", word_count);
}
所有权
use std::collections::HashMap;
fn main() {
let key = String::from("color");
let value = String::from("blue");
let mut map = HashMap::new();
map.insert(key, value);
let key = String::from("color");
let value = String::from("blue");
let mut map = HashMap::new();
map.insert(&key, &value);
println!("{}: {}", key, value);
}
删除
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("a", 1);
map.insert("b", 2);
map.insert("c", 3);
map.remove("b");
map.retain(|_, v| *v > 1);
}
Entry API 详解
use std::collections::HashMap;
fn main() {
let mut map: HashMap<&str, Vec<i32>> = HashMap::new();
map.entry("scores").or_insert_with(Vec::new).push(95);
map.entry("scores").or_insert_with(Vec::new).push(87);
map.entry("scores").or_insert_with(Vec::new).push(92);
println!("{:?}", map["scores"]);
map.entry("grades").or_insert_with(|| vec![0]).push(100);
map.entry("scores").and_modify(|v| v.push(100));
let mut map2: HashMap<&str, Vec<i32>> = HashMap::new();
map2.entry("data").or_default().push(1);
}
实践练习
练习 1:词频统计
use std::collections::HashMap;
fn word_frequency(text: &str) -> HashMap<String, usize> {
let mut freq = HashMap::new();
for word in text.split_whitespace() {
let word = word.to_lowercase();
*freq.entry(word).or_insert(0) += 1;
}
freq
}
fn main() {
let text = "the quick brown fox jumps over the lazy dog the fox";
let freq = word_frequency(text);
let mut sorted: Vec<_> = freq.iter().collect();
sorted.sort_by(|a, b| b.1.cmp(a.1));
for (word, count) in sorted.iter().take(5) {
println!("{}: {}", word, count);
}
}
练习 2:两数之和
use std::collections::HashMap;
fn two_sum(nums: &[i32], target: i32) -> Option<(usize, usize)> {
let mut seen = HashMap::new();
for (i, &num) in nums.iter().enumerate() {
let complement = target - num;
if let Some(&j) = seen.get(&complement) {
return Some((j, i));
}
seen.insert(num, i);
}
None
}
fn main() {
let nums = vec![2, 7, 11, 15];
let target = 9;
match two_sum(&nums, target) {
Some((i, j)) => println!("索引: ({}, {})", i, j),
None => println!("未找到"),
}
}
练习 3:分组
use std::collections::HashMap;
fn group_by_length(words: &[&str]) -> HashMap<usize, Vec<&str>> {
let mut groups = HashMap::new();
for &word in words {
groups.entry(word.len()).or_insert_with(Vec::new).push(word);
}
groups
}
fn main() {
let words = ["hi", "hello", "hey", "world", "rust", "go", "abc"];
let groups = group_by_length(&words);
for (len, words) in &groups {
println!("长度 {}: {:?}", len, words);
}
}
练习 4:LRU 缓存(简化版)
use std::collections::HashMap;
struct Cache {
data: HashMap<String, (String, u64)>,
counter: u64,
capacity: usize,
}
impl Cache {
fn new(capacity: usize) -> Self {
Cache {
data: HashMap::new(),
counter: 0,
capacity,
}
}
fn get(&mut self, key: &str) -> Option<&str> {
if let Some((value, ts)) = self.data.get_mut(key) {
self.counter += 1;
*ts = self.counter;
Some(value.as_str())
} else {
None
}
}
fn put(&mut self, key: String, value: String) {
if self.data.len() >= self.capacity {
if let Some(oldest_key) = self.data.iter()
.min_by_key(|(_, (_, ts))| ts)
.map(|(k, _)| k.clone())
{
self.data.remove(&oldest_key);
}
}
self.counter += 1;
self.data.insert(key, (value, self.counter));
}
}
fn main() {
let mut cache = Cache::new(3);
cache.put("a".into(), "1".into());
cache.put("b".into(), "2".into());
cache.put("c".into(), "3".into());
cache.get("a");
cache.put("d".into(), "4".into());
println!("a: {:?}", cache.get("a"));
println!("b: {:?}", cache.get("b"));
}
常见错误
1. 键类型不支持 Hash
2. get 返回引用
let mut map = HashMap::new();
map.insert("key", vec![1, 2, 3]);
map.get_mut("key").unwrap().push(4);
小结
| 操作 | 语法 |
|---|
| 创建 | HashMap::new() |
| 插入 | insert(key, value) |
| 访问 | get(key) → Option<&V> |
| 更新 | entry(key).or_insert(default) |
| 删除 | remove(key) |
| 遍历 | for (k, v) in &map |