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

news/2024/9/22 14:26:18 标签: rust, 哈希算法, 开发语言

HashMap用法文档

文章目录

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

rust">use std::collections::HashMap;

创建

rust">// 最简单的写法
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。

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

rust">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 匹配。

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

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

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

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

集增改于一身的entry

rust">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。

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

遍历

只读遍历

rust">// 遍历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()

rust">// 可改,但执行完,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)

容量、实际长度、判空

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

导出

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

清除

rust">map.clear();

重定容量

rust">// 容量至少增加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.niftyadmin.cn/n/5670405.html

相关文章

ElasticSearch的搜索方式

目录 目录 前言 数据准备 文档搜索 一、查询所有文档 二、全文检索 &#xff08;1&#xff09;全文检索 &#xff08;2&#xff09;自动纠错 三、范围搜索 四、短语检索 五、单词/词组搜索 六、复合搜索 前言 数据准备 PUT /students {"mappings":{&qu…

IPsec-VPN中文解释

网络括谱图 IPSec-VPN 配置思路 1 配置IP地址 FWA:IP地址的配置 [FW1000-A]interface GigabitEthernet 1/0/0 [FW1000-A-GigabitEthernet1/0/0]ip address 10.1.1.1 24 //配置IP地址 [FW1000-A]interface GigabitEthernet 1/0/2 [FW1000-A-GigabitEthernet1/0/2]ip a…

大数据Flink(一百二十一):Flink CDC基本介绍

文章目录 Flink CDC基本介绍 一、什么是CDC 二、CDC的实现机制 三、​​​​​​​​​​​​​​传统 CDC ETL 分析 四、​​​​​​​​​​​​​​基于 Flink CDC 的 ETL 分析 五、​​​​​​​​​​​​​​什么是 Flink CDC 六、​​​​​​​​​​​​​​…

ARM基础知识点及简单汇编语法

计算机最小系统是一个能启动并运行基本功能的系统&#xff0c;其组成包括&#xff1a; 处理器&#xff08;CPU&#xff09;&#xff1a;执行指令的核心组件。内存&#xff1a; RAM&#xff1a;存储运行中的程序和数据。ROM&#xff1a;存储引导程序或固件。存储&#xff1a;用…

什么是僵尸进程?

僵尸进程是指已经完成执行但仍在进程表中保留其信息的进程。这种状态通常发生在子进程结束后&#xff0c;父进程尚未读取其退出状态&#xff0c;导致子进程的信息仍保留在系统中。僵尸进程不会消耗系统资源&#xff0c;但如果数量过多&#xff0c;可能会影响系统性能。 当一个…

【前端】ES6:Promise对象和Generator函数

文章目录 1 Promise对象1.1 回调地狱1.2 Promise使用1.3 Promise对象的状态1.4 Promise.all1.5 Promise.race 2 Generator函数2.1 基本语法2.2 异步流程2.2.1 手动版本2.2.2 自动版本 1 Promise对象 Promise是异步编程的一种解决方案&#xff0c;比传统的解决方案回调函数&…

掌控历史:如何通过Git版本管理工具提升你的开发效率

先一览全局: git目录 一.打开git二.git bash的基础命令三.配置git四.仓库搭建五.文件操作和状态六.忽略文件七.gitee的使用1.添加公钥2.创建仓库 八.vs中使用git九.git分支常用命令十.文件差异比较十一.文件回溯和推进十二.合并冲突和消除十三.合并/压缩提交十四.远程仓库推拉十…

如何在webots中搭建一个履带机器人

前期准备 下载webotswebots基本知识 a. 官方文档:Webots documentation: Track b. B站教程:webots-超详细入门教程(2020)_哔哩哔哩_bilibili搭建流程 搭建履带机器人主要使用到了webots中的track节点,这个节点是专门用来定义履带的相关属性,模拟履带运动的 首先,创建一个…