当前位置: 首页 > article >正文

【Rust语言】std::collections::HashMap用法

HashMap用法文档

文章目录

  • 创建
      • 键的要求
  • 增删改查
      • 增: insert
      • 删: remove/remove_entry
          • 单点修改 get_mut
          • 整体修改 values_mut/iter_mut
      • 集增改于一身的entry
  • 遍历
      • 只读遍历
      • into_values() 与 into_keys()
      • 容量、实际长度、判空
      • 导出
      • 清除
      • 重定容量

use std::collections::HashMap;

创建

// 最简单的写法
let mut my_map = HashMap::new();

// 写全了就是 ↓
let mut map: HashMap<&str, i32> = HashMap::new();

// 规定初始容量
let mut map: HashMap<&str, i32> = HashMap::with_capacity(10);

// 创建一个使用随机哈希器的 HashMap
use std::hash::RandomState;
let s = RandomState::new();
let mut map = HashMap::with_hasher(s);

// 使用随机哈希器 并且规定初始容量
let mut map = HashMap::with_capacity_and_hasher(10, s);

键的要求

键需要实现 Eq 和 Hash 特征,通常可以使用默认
#[derive(Partial Eq, Eq, Hash)]
如果您自己实现这些属性,则以下属性必须成立:
k1 == k2 -> hash(k1) == hash(k2)

增删改查

增: insert

将键值对插入到映射中。

如果映射不存在此键,则返回 None。

如果映射确实存在此键,则更新该值并返回旧值。

my_map.insert("Daniel", "798-1364");

删: remove/remove_entry

map.remove(&1)
map.remove_entry(&1);
返回Option,若map中有key==1的,则返回Some((1, “a”), 否则返回None

单点修改 get_mut

返回对与 key 对应的值的可变引用。

键可以是映射的键类型的任何借用形式,但借用形式的 Hash 和 Eq 必须与键类型的 Hash 和 Eq 匹配。

// if let 的用法:返回None,则 if语句中不执行(不会报错)
if let Some(x) = map.get_mut(&1) {
    *x = "b";
}
整体修改 values_mut/iter_mut
for (_, val) in map.iter_mut() {
    *val *= 2;
}

for val in map.values_mut() {
    *val = *val + 10;
}

思考:为什么没有key_mut?
答:因为hash map中的key不可改

assert_eq!(map.contains_key(&1), true);// 返回bool类型
map.get_key_value(&1); //返回Option<(&K, &V)类型
map.get(&1)// 返回Option<&V>类型

集增改于一身的entry

letters.entry(ch).and_modify(|counter| *counter += 1).or_insert(1);

解释:

letters.entry(ch):

letters 是一个 HashMap,其中 entry 方法被调用。这个方法接受一个键(在这个例子中是 ch),并返回一个 Entry 类型的值,代表映射中与该键关联的值的入口点。

Entry API 提供了一种方式来迭代、插入或修改映射中的值,而不需要直接使用 get、insert 或 get_mut 方法。

.and_modify(|counter| *counter += 1):

and_modify 方法是一个在 Entry API 中使用的方法,它用于修改已存在的值。如果键 ch 已经存在于映射中,这个方法将被调用。

它接受一个闭包 |counter| *counter += 1,这个闭包接受一个可变引用 counter 到当前的计数值,并递增这个值。这里 *counter += 1 相当于 counter = counter + 1,但使用了解引用操作符 * 来修改值。

.or_insert(1):

or_insert 方法是 Entry API 的一部分,用于处理键不存在的情况。如果 ch 不在映射中,这个方法将被调用。

它接受一个值(在这个例子中是 1),并将这个值插入到映射中作为 ch 的值。如果 ch 已经存在,这个方法不会做任何事情。

综合来看,这行代码的作用是:

  • 如果 ch 已经作为键存在于 letters 映射中,就将其对应的值增加 1。

  • 如果 ch 不存在,就在映射中插入 ch 作为键,并将其值初始化为 1。

这种写法非常适合于计数场景,如统计字符出现的次数,因为它简洁地处理了值的更新和插入。

遍历

只读遍历

// 遍历key
for key in map.keys() {
    println!("{key}");
}

// 遍历value
for val in map.values() {
    println!("{val}");
}

// 遍历键值对
for (key, val) in map.iter() {
    println!("key: {key} val: {val}");
}

into_values() 与 into_keys()

// 可改,但执行完,map就没了,它的所有值已经被移动到迭代器中。开销大,一般不这么用。
// value拥有所有权
for value in map.into_values() {
    println!("{}", value);
}

// 常见用法,效果是把所有的val/key放入Vec中。
let mut vec: Vec<i32> = map.into_values().collect();
let mut vec: Vec<&str> = map.into_keys().collect();

vec.sort_unstable(); //排序

注意:遍历的复杂度是O(capacity),而非O(len)

容量、实际长度、判空

assert!(map.capacity() >= 100);
assert_eq!(a.len(), 0);
assert!(!a.is_empty());

导出

for (k, v) in a.drain().take(1) {
    assert!(k == 1 || k == 2);
    assert!(v == "a" || v == "b");
}

清除

map.clear();

重定容量

// 容量至少增加10
map.reserve(10);

// 尝试容量至少增加10
map.try_reserve(10).expect("why is the test harness OOMing on a handful of bytes?");

// 缩小容量至合适大小
map.shrink_to_fit();

// 缩小至(如果参数比len还小,则该句话被忽略)
map.shrink_to(10);

http://www.kler.cn/a/318399.html

相关文章:

  • 传奇996_21——龙岭事件
  • MFC工控项目实例二十九主对话框调用子对话框设定参数值
  • 性能测试|JMeter接口与性能测试项目
  • Unity学习笔记(4):人物和基本组件
  • AMD CPU下pytorch 多GPU运行卡死和死锁解决
  • 浅谈C#之内存管理
  • Linux环境下安装部署MySQL8.0以上(内置保姆级教程) C语言
  • Oracle数据库expdp与impdp
  • 基于SpringBoot+Vue+MySQL的网上租赁系统
  • CVPR最牛图像评价算法!
  • webview2加载本地页面
  • 「JavaScript深入」一文吃透JS的基本数据类型 Symbol
  • 统信服务器操作系统【Cron定时任务服务】
  • 安装程序不用鼠标,Windows也玩程序包管理存储库
  • 敏感词过滤
  • uni-app 多环境配置
  • 项目实战 (15)--- 代码区块重构及相关技术落地
  • 8月份,AI图像生成领域web端产品排行榜及产品是做什么的
  • UniApp一句话经验: px -> rpx动态转换和动态元素区域的获取
  • 前端-js例子:tab切换
  • 如何使用爬虫挖掘更多长尾关键词
  • HashMap五大核心问题总结
  • SpringMVC后续4
  • arm开发板通信
  • Goweb预防XSS攻击
  • 【算法笔记】二分查找 红蓝染色法