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

【Rust自学】8.5. HashMap Pt.1:HashMap的定义、创建、合并与访问

8.5.0. 本章内容

第八章主要讲的是Rust中常见的集合。Rust中提供了很多集合类型的数据结构,这些集合可以包含很多值。但是第八章所讲的集合与数组和元组有所不同。

第八章中的集合是存储在堆内存上而非栈内存上的,这也意味着这些集合的数据大小无需在编译时就确定,在运行时它们可以动态地变大或变小。

本章主要会讲三种集合:Vector、String和HashMap(本文)

喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)

8.5.1. 什么是HashMap

HashMap的形式是HashMap<K,V>,其中K代表键(key),V代表值(value)。HashMap以键值对的形式存储数据,一个键对应一个值。很多语言都支持这样的集合数据结构,但是不一定是这个叫法,比如说C#中相同概念的数据结构叫字典(dictionary)。

HashMap的内部实现使用了Hash函数,中文叫哈希函数,这个函数决定了如何在内存中存储键与值。

Vector中我们使用索引来访问数据,但有的时候你想要的是通过键(键可以是任何数据类型)来寻找数据,而不是通过索引(或者说你不清楚这个数据在哪个索引)。这种情况就可以使用HashMap。

需要注意的是,HashMap是同构的,也就是说在一个HashMap中,所有的键必须是同一类型,所有的值必须是同一类型。

8.5.2. 创建HashMap

  • 由于HashMap不常用,所以Rust并没有把它集成到预导入模块(Prelude),使用前需要引入HashMap,在代码开头写上:use std::collections::HashMap;
  • 创建空的HashMap使用Hash::new()函数
  • 添加数据使用insert()方法

看个例子:

use std::collections::HashMap;  fn main() {  let mut scores:HashMap<String, i32> = HashMap::new();  
}

在这里创建了一个名为scores的变量来存储HashMap,由于Rust是强语言类型,它必须知道你在HashMap里存储什么数据类型。又因为没有前后文可供编译器推断,所以在声明时就必须把HashMap里键和值的数据类型显式声明出来,在代码中就是scores的键被设为了String类型,值被设为了i32类型。

当然,如果你在后文给这个HashMap上添加了数据,Rust就会根据添加的数据类型自动推断键和值的数据类型。添加数据使用insert()方法。例子如下:

use std::collections::HashMap;  fn main() {  let mut scores = HashMap::new();  scores.insert(String::from("dev1ce"), 0);
}

因为在第5行往scores里添加了键值对,且键String::from("dev1ce")String类型,值0是i32(Rust默认整数是i32)类型,所以编译器就会自己推断出scores是一个HashMap<String, i32>类型的HashMap,因此第四行在声明时就不需要显式声明了。

8.5.3. 将两个Vector合为一个HashMap

在元素类型为元组的Vector上使用collect方法,可以使用HashMap。换个说法,假如你有两个Vector,这两个Vector上的所有值都有一一对应关系,这个时候就可以使用collect方法,把一个Vector里的数据作为键,另一个作为值,放到HashMap里。如下例:

use std::collections::HashMap;  fn main() {  let player = vec![String::from("dev1ce"), String::from("Zywoo")];  let initial_scores = vec![0, 100];  let scores: HashMap<_, _> = player.iter().zip(initial_scores.iter()).collect();  
}
  • player这个Vector是用来存储选手名字的,里面的元素是String类型
  • initial_scores这个Vector是用来存储每个选手对应的得分的
  • player.iter()initial_scores.iter()是两个Vector的遍历器,使用.zip()方法就可以创建一个元组的数组,player.iter().zip(initial_scores.iter())就是创建一个player中的元素在前,initial_scores中的元素在后的元组数组,想换元素位置就可以把代码中的两个迭代器呼唤位置即可。然后再使用.collect()方法来把元组转化为HashMap。
  • 最后要注意的一点是.collect()它支持转换为很多数据结构,如果声明时不显式声明其类型程序就会报错,这里就指明了类型是HashMap<_, _><>中的两个数据类型编译器可以根据代码(也就是找两个的Vector的数据类型)来推断,所以这里可以写_占位符让它自行推断。

8.5.4. HashMap和所有权

对于实现了Copy trait的数据类型(例如i32在内的绝大多数简单数据类型),值会被复制到HashMap中,原先的变量仍然可用。对于没有实现的(例如String),所有权会被交给HashMap。

如果将值的引用插入到HashMap,值本身就不会移动。在HashMap的有效期间,被引用的值必须保持有效。

8.5.5. 访问HashMap中的值

访问值可以使用get方法。get方法的参数是HashMap的键,返回值是Option<&V>这个枚举。看个例子:

use std::collections::HashMap;  fn main() {  let mut scores = HashMap::new();  scores.insert(String::from("dev1ce"), 0);  scores.insert(String::from("Zywoo"), 100);let player_name = String::from("dev1ce");  let score = scores.get(&player_name);  match score {  Some(score) => println!("{}", score),  None => println!("Player not found"),  };  
}
  • 首先创建了一个空的HashMap叫做scores,然后又通过insert方法往里面添加了两个键值对(“dev1ce”, 0)和(“Zywoo”, 100),键类型是String,值类型是i32
  • 然后又声明了名为player_nameString变量,其值为"dev1ce"。
  • 接着就通过HashMap上的get方法在scoresplayer_name&表示引用)这个键所对应的值,但是get方法返回的是Option枚举,所以这里先把这个Option枚举值赋给score后面再来解包。
  • 最后使用了match表达式来处理score,如果找到了对应的值,score这个枚举类型就会是变体Some,把Some所关联的值绑定在score上,然后再打印出来。如果找不到,score这个枚举类型就会是变体None,这个时候就会打印"Player not found"。

输出:

0

8.5.6. 遍历HashMap

遍历HashMap一般使用for循环。如下例:

use std::collections::HashMap;  fn main() {  let mut scores = HashMap::new();  scores.insert(String::from("dev1ce"), 0);  scores.insert(String::from("Zywoo"), 100);  for (k, v) in &scores {  println!("{}: {}", k, v);  }  
}

这个for循环使用的是HashMap的引用,也就是&scores,因为通常遍历之后还要继续使用这个HashMap,所以使用引用就不会失去所有权,前面的(k,v)是一个模式匹配,第一个值就是键,这里赋给了k;第二个是值,这里赋给了v

输出:

Zywoo: 100
dev1ce: 0

相关文章:

【Rust自学】8.5. HashMap Pt.1:HashMap的定义、创建、合并与访问

8.5.0. 本章内容 第八章主要讲的是Rust中常见的集合。Rust中提供了很多集合类型的数据结构&#xff0c;这些集合可以包含很多值。但是第八章所讲的集合与数组和元组有所不同。 第八章中的集合是存储在堆内存上而非栈内存上的&#xff0c;这也意味着这些集合的数据大小无需在编…...

未来网络技术的新征程:5G、物联网与边缘计算(10/10)

一、5G 网络&#xff1a;引领未来通信新潮流 &#xff08;一&#xff09;5G 网络的特点 高速率&#xff1a;5G 依托良好技术架构&#xff0c;提供更高的网络速度&#xff0c;峰值要求不低于 20Gb/s&#xff0c;下载速度最高达 10Gbps。相比 4G 网络&#xff0c;5G 的基站速度…...

LLM(十二)| DeepSeek-V3 技术报告深度解读——开源模型的巅峰之作

近年来&#xff0c;大型语言模型&#xff08;LLMs&#xff09;的发展突飞猛进&#xff0c;逐步缩小了与通用人工智能&#xff08;AGI&#xff09;的差距。DeepSeek-AI 团队最新发布的 DeepSeek-V3&#xff0c;作为一款强大的混合专家模型&#xff08;Mixture-of-Experts, MoE&a…...

Uniapp在浏览器拉起导航

Uniapp在浏览器拉起导航 最近涉及到要在浏览器中拉起导航&#xff0c;对目标点进行路线规划等功能&#xff0c;踩了一些坑&#xff0c;找到了使用方法。&#xff08;浏览器拉起&#xff09; 效果展示 可以拉起三大平台及苹果导航 点击选中某个导航&#xff0c;会携带经纬度跳转…...

公平联邦学习——多目标优化

前言 前段时间接触到了联邦学习&#xff08;Federated Learning, FL&#xff09;。涉猎了几年多目标优化的我&#xff0c;惊奇地发现横向联邦学习里面也有用多目标优化来做的。于是有感而发&#xff0c;特此写一篇博客记录记录&#xff0c;如有机会可以和大家多多交流。遇到不…...

奇怪的Python:为何字符串要设置成不可变的?

你好&#xff01;我是老邓。今天我们来聊聊 Python 中字符串不可变这个话题。 1、问题简介&#xff1a; Python 中&#xff0c;字符串属于不可变对象。这意味着一旦字符串被创建&#xff0c;它的值就无法被修改。任何看似修改字符串的操作&#xff0c;实际上都是创建了一个新…...

Vue-Router之嵌套路由

在路由配置中&#xff0c;配置children import Vue from vue import VueRouter from vue-routerVue.use(VueRouter)const router new VueRouter({mode: history,base: import.meta.env.BASE_URL,routes: [{path: /,redirect: /home},{path: /home,name: home,component: () &…...

MyBatis使用的设计模式

目录 1. 工厂模式&#xff08;Factory Pattern&#xff09; 2. 单例模式&#xff08;Singleton Pattern&#xff09; 3. 代理模式&#xff08;Proxy Pattern&#xff09; 4. 装饰器模式&#xff08;Decorator Pattern&#xff09; 5. 观察者模式&#xff08;Observer Patt…...

arm rk3588 升级glibc2.31到2.33

一、查看glibc版本 rootztl:~# ldd --version ldd (Ubuntu GLIBC 2.31-0ubuntu9.2) 2.31 Copyright (C) 2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNE…...

【Linux系列】sed命令的深入解析:如何使用sed删除文件内容

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

C++ 设计模式:桥接模式(Bridge Pattern)

链接&#xff1a;C 设计模式 链接&#xff1a;C 设计模式 - 装饰模式 桥接模式&#xff08;Bridge Pattern&#xff09;是一种结构型设计模式&#xff0c;它通过将抽象部分&#xff08;业务功能&#xff09;与实现部分&#xff08;平台实现&#xff09;分离&#xff0c;使它们…...

MATLAB中whitespacePattern函数用法

目录 语法 说明 示例 匹配空白字符 替换非标准空白 更正错误的间距 whitespacePattern函数的功能是匹配空白字符。 语法 pat whitespacePattern pat whitespacePattern(N) pat whitespacePattern(minCharacters,maxCharacters) 说明 pat whitespacePattern 创建一…...

Django多字段认证的实现

Django多字段认证 需求&#xff1a; django认证的检查用户是username&#xff0c;如果使用 username和 手机号验证登录。 重写&#xff1a; ModelBackend 类下的 authenticate 方法 # 在对应应用下创建 utils.py""" 修改Django认证类&#xff0c;为了实现 …...

【AndroidAPP】权限被拒绝:[android.permission.READ_EXTERNAL_STORAGE],USB设备访问权限系统报错

一、问题原因 1.安卓安全性变更 Android 12 的安全性变更&#xff0c;Google 引入了更严格的 PendingIntent 安全管理&#xff0c;强制要求开发者明确指定 PendingIntent 的可变性&#xff08;Mutable&#xff09;或不可变性&#xff08;Immutable&#xff09;。 但是&#xf…...

SQL进阶技巧:如何分析连续签到领金币数问题?

目录 0 题目需求 1 数据准备 2 问题分析 2.1 代码实现 2.2 代码功能分析 第一段 SQL...

1、ELK的架构和安装

ELK简介 elk&#xff1a;elasticsearch logstash kibana&#xff0c;统一日志收集系统。 elasticsearch&#xff1a;分布式的全文索引引擎的非关系数据库&#xff0c;json格式&#xff0c;在elk中存储所有的日志信息&#xff0c;架构有主和从&#xff0c;最少需要2台。 …...

Vue2/Vue3使用DataV

Vue2 注意vue2与3安装DataV命令命令是不同的Vue3 DataV - Vue3 官网地址 注意vue2与3安装DataV命令命令是不同的 vue3vite 与 Vue3webpack 对应安装也不同vue3vite npm install kjgl77/datav-vue3全局引入 // main.ts中全局引入 import { createApp } from vue import Da…...

汇编环境搭建

学习视频 将MASM所在目录 指定为C盘...

Android 系统 `android.app.Fragment` 类的深度定制与常见问题解析

Android 系统 android.app.Fragment 类的深度定制与常见问题解析 目录 引言Fragment 概述Fragment 的生命周期Fragment 的系统层深度定制 4.1 Fragment 的创建与初始化4.2 Fragment 的布局与视图4.3 Fragment 的通信机制4.4 Fragment 的动画与过渡4.5 Fragment 的状态保存与恢…...

linux ueditor nginx https 后台配置项返回格式出错,上传功能将不能正常使用

jsp的版本 如果出现了这个错误&#xff0c;上传的图标都亮起的情况&#xff0c;还是提示这个&#xff0c; 可以试试修改 uedtior.all.js 8082行 isJsonp utils.isCrossDomainUrl(configUrl); 改为 // isJsonp utils.isCrossDomainUrl(configUrl); isJsonp true; 如果还不…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...

OCR MLLM Evaluation

为什么需要评测体系&#xff1f;——背景与矛盾 ​​ 能干的事&#xff1a;​​ 看清楚发票、身份证上的字&#xff08;准确率>90%&#xff09;&#xff0c;速度飞快&#xff08;眨眼间完成&#xff09;。​​干不了的事&#xff1a;​​ 碰到复杂表格&#xff08;合并单元…...