趣味学RUST基础篇(HashMap)

HashMap<K, V>:Rust 里的"魔法储物柜"!

学些HashMap,我们还是举个栗子说明:假设你开了一家超市

  • 顾客不会说:"我要第三排第二个货架上的东西。"
  • 他们会说:"我要一包蓝龙牌辣条 !" 或者 "来一瓶黄泉牌汽水!"

你总不能靠数货架来找商品吧?你需要一个智能货架系统------

这就是 HashMap 的用武之地!

什么是哈希映射(HashMap)?

HashMap<K, V> 就像一个魔法储物柜

  • 每个抽屉都有一个标签(Key)
  • 抽屉里放着对应的物品(Value)

比如:

rust 复制代码
"蓝队" → 10 分  
"黄队" → 50 分

你想查蓝队得分?直接问:"蓝队多少分? " → 系统秒回:10

它不靠"第几个",而是靠"叫什么"来查找,又快又准


使用前:先开门!

HashMap 不在 Rust 的"默认工具包"里,得先开门:

rust 复制代码
use std::collections::HashMap;

就像你要用特殊保险柜,得先申请权限。


创建一个"魔法储物柜"

1. 新建空柜子

rust 复制代码
let mut scores = HashMap::new();

2. 往里放东西:insert

rust 复制代码
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);

现在柜子里有:

复制代码
{
  "Blue": 10,
  "Yellow": 50
}

键(Key)和值(Value)可以是任意类型!

但所有键必须同类型,所有值也必须同类型(同质性)


怎么查东西?用 get 方法!

想查蓝队分数?

rust 复制代码
let team = String::from("Blue");
let score = scores.get(&team);  // 返回 Option<&i32>

注意:

  • get 返回的是 Option<&V>,因为可能没有这个键
  • 所以你得处理 SomeNone

更常见的写法是:

rust 复制代码
let score = scores.get(&team).copied().unwrap_or(0);
// 如果没有,就默认为 0

.copied():把 &i32 变成 i32(因为 i32 可以复制)

.unwrap_or(0):没有就返回 0


遍历所有商品:for 循环

想看看柜子里都有啥?

rust 复制代码
for (team, &score) in &scores {
    println!("{team}: {score}");
}

输出可能是:

text 复制代码
Yellow: 50
Blue: 10

顺序是随机的HashMap 不保证顺序(它是哈希的,不是列表)。


所有权规则:放进去了,就归我了!

看这段代码:

rust 复制代码
let name = String::from("Favorite color");
let value = String::from("Blue");

let mut map = HashMap::new();
map.insert(name, value);

println!("{}", name); // 编译错误!

为什么?因为 insert 拿走了 namevalue 的所有权

就像你把身份证交给银行办业务,办完前你不能再用它。

解决方案:插入引用

rust 复制代码
map.insert(&name, &value); // 插入引用

但注意:这些引用必须活得比 HashMap,否则会变成"悬空指针"!


更新储物柜:三种策略

策略一:直接覆盖(暴力更新)

rust 复制代码
scores.insert("Blue", 25); // 老值 10 被干掉!

简单粗暴,适合"最新值最重要"的场景。


策略二:只在没有时才插入(谨慎更新)

你想加个新队,但不想覆盖旧数据

rust 复制代码
scores.entry("Red").or_insert(30);
  • 如果 "Red" 没有,就插入 30
  • 如果已有,就不动它

entry()HashMap神级 API

它返回一个"入口"(Entry),你可以用 or_insertor_insert_with 等方法智能操作。


策略三:基于旧值更新(智能叠加)

最经典的例子:词频统计

rust 复制代码
let text = "hello world hello rust world";

let mut word_count = HashMap::new();

for word in text.split_whitespace() {
    let count = word_count.entry(word).or_insert(0);
    *count += 1;  // 解引用后 +1
}

结果:

rust 复制代码
{
  "hello": 2,
  "world": 2,
  "rust": 1
}

关键点:

  • or_insert(0) 返回 &mut i32(可变引用)
  • *count += 1 修改它
  • 引用在循环结束时自动释放,安全!

哈希函数:柜子背后的"分拣机器人"

HashMap 为什么这么快?因为它用哈希函数把钥匙(Key)变成"抽屉编号"。

Rust 默认用 SipHash

  • 安全:防黑客攻击(防止"哈希碰撞攻击")
  • 稍慢:不是最快的算法

如果你发现性能瓶颈,可以换更快的 hasher(比如 ahash),但一般没必要。

想换?去 crates.io 找找看!

小结:HashMap 使用口诀

操作 方法
创建 HashMap::new()
插入 insert(key, value)
查询 get(&key) → 返回 Option<&V>
遍历 for (k, v) in &map
智能插入 entry(key).or_insert(value)
词频统计 *entry(key).or_insert(0) += 1
所有权 值会被 move,引用需注意生命周期

三神器合体:Rust 冒险者工具箱

容器 别名 适用场景
Vec<T> 魔法背包 有序列表,按索引访问
String 魔法卷轴 存文本,支持 UTF-8
HashMap<K,V> 魔法储物柜 键值对,快速查找
相关推荐
灵犀学长10 小时前
Spring Boot集成Kafka常见业务场景最佳实践实战指南
java·spring boot·后端·kafka
lskblog10 小时前
使用 PHP Imagick 扩展实现高质量 PDF 转图片功能
android·开发语言·前端·pdf·word·php·laravel
梅坞茶坊10 小时前
PHP操作LibreOffice将替换变量后的word文件转换为PDF文件
开发语言·c#
丑小鸭是白天鹅10 小时前
嵌入式C语言之链表冒泡排序
c语言·开发语言·链表
通往曙光的路上10 小时前
JAVA 十二幕啦啦啦啦啦啦啦啊啦啦啦啦a
java·开发语言·算法
Sagittarius_A*10 小时前
SpringBoot Web 入门指南:从零搭建第一个SpringBoot程序
java·前端·spring boot·后端
Livingbody10 小时前
【LIC·2025语言与智能技术竞赛——人民日报健康客户端赛道一】赛题解析
后端
芜青10 小时前
JavaScript手录进阶01-跨域问题
开发语言·javascript·ajax·ecmascript
珹洺10 小时前
C++从入门到实战(二十一)List迭代器实现
开发语言·c++·list
Livingbody10 小时前
《LIC·2025语言与智能技术竞赛——智源研究院赛道二》数据处理分析
后端