【Rust】008-常用集合

【Rust】008-常用集合

文章目录

  • 【Rust】008-常用集合
  • 一、动态数组: `Vec<T>`
    • 1、引入
    • 2、三种常见初始化方式
      • 第一种:初始化一个长度为零且不进行内存分配的数组
      • 第二种:初始化一个长度为零但提前分配好16个元素大小内存的数组
      • 第三种:使用`vec!`宏创建数组并初始化元素
      • 其它写法
    • 3、添加、访问与修改数组元素
    • 4、删除元素
    • 5、遍历元素
  • 二、HashMap<K, V>
    • 1、引入
    • 2、两种常见初始化方式
      • 第一种:使用 `new`
      • 第二种:使用 `with_capacity`
    • 3、对元素的增删改查与遍历

一、动态数组: Vec<T>

1、引入

在Java中,List接口是一个非常常用的数据结构接口,它定义了一组可以用于操作有序集合的方法。ArrayListList接口的一个常见实现,提供了动态数组的功能。通过ArrayList,我们可以方便地进行元素的添加、删除和访问

如果你熟悉Java的ArrayList,那么理解Rust的Vec<T>会相对容易。以下是从ListArrayList引出Rust的Vec<T>的一些要点:

  1. 动态数组的概念

    • 在Java中,ArrayList实现了List接口,是一个可以动态调整大小的数组。它通过在内部维护一个可变大小的数组来实现这一点,并在需要时自动扩展。
    • 在Rust中,Vec<T>是一个动态数组,类似于Java的ArrayList。它可以根据需要动态扩展和缩小,存储同一类型的元素。
  2. 创建和初始化

    • 在Java中,创建一个ArrayList通常是通过new ArrayList<>()
    • 在Rust中,创建一个Vec可以通过Vec::new()或者使用宏vec![]来初始化。
  3. 添加元素

    • ArrayList使用add()方法来添加元素。
    • Vec<T>使用push()方法来添加元素。
  4. 访问元素

    • ArrayList中,可以使用get(index)方法来访问元素。
    • Vec<T>中,可以使用索引语法vec[index]来访问元素。
  5. 删除元素

    • ArrayList提供了remove(index)方法来删除指定位置的元素。
    • Vec<T>提供了remove(index)方法来删除指定位置的元素。
  6. 性能和内存管理

    • ArrayList依赖于Java的垃圾回收机制来管理内存。
    • Vec<T>则利用Rust的所有权系统来自动管理内存,确保在不再需要时自动释放。
  7. 线程安全

    • ArrayList不是线程安全的,但Java提供了其他线程安全的集合类。
    • Vec<T>也不是线程安全的,需要在多线程环境中使用同步机制来保护。

2、三种常见初始化方式

第一种:初始化一个长度为零且不进行内存分配的数组

这种方式使用Vec::new()方法。此方法创建一个空的Vec,长度为零,并且初始时不分配额外的内存空间。

场景:这种方式适合在不确定具体容量需求的情况下使用,Rust会在需要时自动分配内存。

let v: Vec<String> = Vec::new();

第二种:初始化一个长度为零但提前分配好16个元素大小内存的数组

使用Vec::with_capacity(16)方法。这会创建一个空的Vec,长度为零,但预先分配了可以容纳16个元素的内存。

场景:这种方式适合当你知道大致需要多少容量时使用,可以减少内存重新分配的开销,提高性能。

let mut v: Vec<String> = Vec::with_capacity(16);

第三种:使用vec!宏创建数组并初始化元素

vec!宏是Rust中用于创建Vec的便捷方式,可以直接初始化Vec并填入元素。

场景:这种方式适合在需要立即初始化并填充数据的情况下使用,代码简洁直观。

let v = vec!["hello".to_string(), "world".to_string()];

番外:为什么要这么写““hello”.to_string()”,直接写“hello”如何?

当你直接写"hello"时,编译器会将其视为字符串切片类型&str。如果你需要一个String(例如在创建Vec<String>时),你必须将&str转换为String。这就是为什么使用"hello".to_string()的原因。to_string()方法会将一个字符串切片转换为一个String类型。

参考链接:Rust 中的字符串类型:&strString:https://blog.csdn.net/qq_29689343/article/details/137350142


其它写法

Rust 有类型推导的能力

fn this_also_works() {let mut v = Vec::new(); // 这里可以先不指定类型v.push("str");          // 在这里,编译器会通过元素的类型确定 v 的类型,为 Vec<&str>
}

直接指定泛型类型

fn this_also_works2() {let _ = Vec::<String>::new();
}

3、添加、访问与修改数组元素

通过.push方法添加一个元素,可以通过下标[i]的方式访问数组元素,如果i超过数组长度,程序直接 panic。

fn get_by_index() {let mut v = Vec::new();// 通过`.push`方法添加一个元素v.push(1);v.push(2);println!("{}", v[1]); // 输出 2println!("{}", v[2]); // 这里程序会直接退出
}

那有没有不会 panic 的方式呢?有的,我们可以通过.get 的方法,该函数的返回的是Option<&T>,如果数组越界了,会返回 None。(不过因为会多一次检查,这种方式性能会差一点)。

fn get_by_index() {let mut v = Vec::new();v.push(1);v.push(2);println!("{:?}", v.get(1)); // 输出 Some(2)println!("{:?}", v.get(2)); // 输出 None
}

通过下标修改数组元素

fn modify_by_index() {let mut v = Vec::new();v.push(1);v.push(2);v[0] = 100;println!("{}", v[0]); // 会输出 100
}

4、删除元素

可以通.pop将数组的最后一个元素弹出来,如果数组为空,则返回 None

fn pop_elem() {let mut v = vec!["Hello", "Rust"];println!("{:?}", v.pop()); // 输出 Some("Rust")
}

还可以通过.remove移出指定下标的元素,且该方法会保持数组元素原来的顺序。也可以通过.swap_remove来移除,不过这个会将数组最后一个元素移到被删除的位置,不能保持数组元素原来的顺序。(第二种方式好奇怪!)。

fn main() {let mut v = vec!["1", "2", "3", "4", "5"];v.remove(1);println!("{:?}", v); // ["1", "3", "4", "5"]v.swap_remove(1);println!("{:?}", v); // ["1", "5", "4"]
}

5、遍历元素

遍历元素要特别注意所有权, for是会消耗变量的。

fn will_consume_v() {let v = vec!["Hello", "World"];for elem in v {println!("{elem}");}println!("{:?}", v); // 这行将会报错,因为我们在第三行的 for 已经将 v 给消耗掉了
}

为了避免被消耗掉v,我们可以对v取引用,这样拿到的elem则会是&T类型:

fn willnot_consume_v() {let v = vec!["Hello", "World"];for elem in &v {println!("{elem}");}println!("{:?}", v); // 这行会正常输出
}

如果想对元素进行修改,可以对v取可变引用

fn modify_elem() {let mut v = vec!["Hello", "World"];for elem in &mut v {// *elem 注意这个写法*elem = "elem"}println!("{:?}", v); // 这行会输出 ["elem", "elem"]
}

二、HashMap<K, V>

1、引入

如果你熟悉 Java 的 HashMap,并且想要在 Rust 中使用类似的功能,以下是一些关键点和步骤,可以帮助你顺利过渡:

  1. 创建 HashMap

    • 在 Java 中,你通常会这样创建一个 HashMap
      Map<String, Integer> map = new HashMap<>();
      
    • 在 Rust 中,你需要引入标准库的集合模块,然后创建一个 HashMap
      use std::collections::HashMap;let mut map = HashMap::new();
      
  2. 插入键值对

    • Java 中的插入操作使用 put 方法:
      map.put("key", 1);
      
    • Rust 中使用 insert 方法:
      map.insert("key", 1);
      
  3. 访问值

    • 在 Java 中,你可以使用 get 方法来访问值:
      Integer value = map.get("key");
      
    • Rust 中的 get 方法返回一个 Option,因为键可能不存在:
      if let Some(&value) = map.get("key") {println!("Value: {}", value);
      }
      
  4. 迭代

    • Java 中可以使用 entrySet 来迭代:
      for (Map.Entry<String, Integer> entry : map.entrySet()) {System.out.println(entry.getKey() + ": " + entry.getValue());
      }
      
    • 在 Rust 中,你可以使用 iter 方法:
      for (key, value) in &map {println!("{}: {}", key, value);
      }
      
  5. 删除键值对

    • Java 使用 remove 方法:
      map.remove("key");
      
    • Rust 也使用 remove 方法:
      map.remove("key");
      
  6. 检查键的存在性

    • Java 中可以使用 containsKey 方法:
      if (map.containsKey("key")) {// do something
      }
      
    • 在 Rust 中,你可以使用 contains_key 方法:
      if map.contains_key("key") {// do something
      }
      
  7. 注意事项

    • Rust 中的 HashMap 默认不是线程安全的。如果你需要在多线程环境中使用,可以考虑使用 MutexRwLock 来保护它。
    • Rust 的 HashMap 使用泛型,确保在编译时进行类型检查,避免了许多运行时错误。

2、两种常见初始化方式

第一种:使用 new

HashMap::new() 创建一个空的 HashMap,默认情况下具有一定的初始容量,但具体的容量可能会根据实现和编译器的不同而有所变化。

use std::collections::HashMap;let mut map = HashMap::new();

第二种:使用 with_capacity

HashMap::with_capacity(capacity) 创建一个具有指定初始容量的 HashMap。这对于知道大概要插入多少元素的情况特别有用,可以减少在插入过程中可能发生的内存重新分配。

use std::collections::HashMap;let mut map = HashMap::with_capacity(10);

3、对元素的增删改查与遍历

use std::collections::HashMap;fn main() {// 创建一个新的 HashMaplet mut map = HashMap::new();// ## 1、添加元素// 使用 insert 方法添加键值对map.insert("apple", 3);map.insert("banana", 5);map.insert("orange", 2);// 此时,map 包含了三个键值对:("apple", 3), ("banana", 5), ("orange", 2)// ## 2、访问元素// 使用 get 方法访问元素,get 返回的是 Option<&V>if let Some(&count) = map.get("apple") {println!("apple 的数量是:{}", count);} else {println!("apple 不存在于 map 中");}// 如果键存在,打印其对应的值;否则,说明键不存在// ## 3、修改元素// 直接使用 insert 方法可以修改元素的值map.insert("banana", 10);// 现在 "banana" 对应的值被修改为 10// 另一种修改方法是使用 entry APImap.entry("orange").and_modify(|count| *count += 1);// 使用 and_modify 仅在键存在时修改其值,将 "orange" 的数量加 1// ## 4、删除元素// 使用 remove 方法删除键值对map.remove("apple");// "apple" 及其对应的值从 map 中被移除// ## 5、遍历元素// 使用迭代器来遍历 HashMap 中的所有键值对for (key, value) in &map {println!("{}: {}", key, value);}// 这将打印出剩余的键值对,格式为 "键: 值"// 为了不消耗掉所有权,可以用&map或者&mut map去遍历。不过相应的,遍历元素的类型也会变成引用。
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/52711.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于YOLO深度学习和百度AI接口的手势识别与控制项目

基于YOLO深度学习和百度AI接口的手势识别与控制项目 项目描述 本项目旨在开发一个手势识别与控制系统&#xff0c;该系统能够通过摄像头捕捉用户的手势&#xff0c;并通过YOLO深度学习模型或调用百度AI接口进行手势识别。识别到的手势可以用来控制计算机界面的操作&#xff0…

同样实用的CSS剪裁属性clip-path

clip-path CSS 属性是一个强大的工具&#xff0c;它允许你创建复杂的形状来剪裁元素的可视区域。这意味着你可以指定一个元素仅显示其形状内的部分&#xff0c;其余部分则不可见。这在创建独特的设计效果时特别有用&#xff0c;比如按钮、图片、文本或其他任何HTML元素。 基本…

浅谈WebApi

一、基本介绍 Web API&#xff08;Web应用程序编程接口&#xff09;是一种用于构建应用程序的接口&#xff0c;它允许软件应用程序通过HTTP请求与Web服务器进行交互。Web API通常用于构建客户端-服务器应用程序&#xff0c;其中客户端可以是Web浏览器、移动应用程序、桌面应用程…

单机docker-compose部署minio

单机多副本docker-compose部署minio 简单介绍 如果服务器有限可以单机挂载多硬盘实现多副本容错&#xff08;生产不推荐&#xff09; 部署好的文件状态 有两个重要文件 docker-compose.yaml和nginx.conf docker-compose.yaml是docker部署容器的配置信息包括4个minio和1个ng…

[数据集][目标检测]男女性别检测数据集VOC+YOLO格式9769张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;9769 标注数量(xml文件个数)&#xff1a;9769 标注数量(txt文件个数)&#xff1a;9769 标注…

Miracast/WifiDisplay开发相关的深入调研分析-android投屏实战开发

Miracast/WifiDisplay概念介绍 Miracast Miracast是由Wi-Fi联盟于2012年所制定&#xff0c;以Wi-Fi直连&#xff08;Wi-Fi Direct&#xff09;为基础的无线显示标准。支持此标准的消费性电子产品&#xff08;又称3C设备&#xff09;可透过无线方式分享视频画面&#xff0c;例如…

CSS学习17--CSS3 过渡、2D变形、3D变形、动画

CSS3 过渡、2D变形、3D变形、动画 一、过渡二、2D变形 transform1.移动 translate2.缩放 scale3. 旋转 rotate4. 倾斜 skew 三、3D变形1. rotateX&#xff08;&#xff09;rotateY&#xff08;&#xff09; rotateZ&#xff08;&#xff09;2. 体会透视 perspective3. translat…

Array对象:

4.1 创建数组对象 var arrObnew Array(值,........) var arrObArray(值,.......) var arrOb[值,.........] var arrObnew Array(n); arrOb[0]值1; arrOb[1]值2; ....... 4.2 属性 length //数组中元素的数目 4.3 方法 转为字符串 String() //将数组转换为字符串&#x…

vue项目本地可以访问接口,浏览器输入接口可以访问数据,部署到服务器无法报接口404

需求变动&#xff0c;原本访问python的后端接口&#xff0c;现在新增Java的接口 新增的接口在服务器上一直404 &#xff0c;本地正常&#xff0c;浏览器输入路径正常。 两个后端不同端口&#xff0c;前端配置了两个转发如下&#xff1a; dev: {// PathsassetsSubDirectory: st…

虚拟现实智能家居实训系统实训解决方案

随着科技的飞速发展&#xff0c;智能家居已成为现代生活的重要组成部分&#xff0c;它不仅极大地提升了居住的便捷性与舒适度&#xff0c;还推动了物联网、大数据、人工智能等前沿技术的融合应用。为了满足市场对智能家居专业人才日益增长的需求&#xff0c;虚拟现实智能家居实…

搭建 WordPress 及常见问题与解决办法

浪浪云活动链接 &#xff1a;https://langlangy.cn/?i8afa52 文章目录 环境准备安装 LAMP 堆栈 (Linux, Apache, MySQL, PHP)配置 MySQL 数据库 安装 WordPress配置 WordPress常见问题及解决办法数据库连接错误白屏问题插件或主题冲突内存限制错误 本文旨在介绍如何在服务器上…

Linux下vscode配置C++和python编译调试环境

Visual Studio Code (简称 VSCode) 是由微软开发的一款免费、开源、跨平台的代码编辑器。它支持 Windows、macOS 和 Linux 操作系统&#xff0c;并且内置对多种编程语言的支持&#xff0c;包括但不限于 C/C、Python、JavaScript、TypeScript、Java 和 Go 等。VSCode 主要用于编…

HarmonyOS ArkUI 构建布局

文章目录 一、构建布局1.线性布局 (Row/Column)1.1 Blank空白填充组件1.2 layoutWeight 自适应缩放1.3 自适应延伸 2.弹性布局 (Flex)3.栅格布局 (GridRow/GridCol)3.创建列表 (List) 一、构建布局 1.线性布局 (Row/Column) 线性布局文档 通过线性容器Row和Column构建 Column…

SpringBoot项目获取统一前缀配置以及获取非确定名称配置

SpringBoot项目获取统一前缀配置以及获取非确定名称配置 在SpringBoot项目中&#xff0c;我们经常看到统一前缀的配置&#xff0c;我们该怎么统一获取 my.config.a.namexiaoming my.config.a.age18 my.config.a.addressguangdong my.config.b.namexiaomli my.config.b.age20 my…

《深度学习》OpenCV 高阶 图像金字塔 用法解析及案例实现

目录 一、图像金字塔 1、什么是图像金字塔 2、图像金字塔作用 1&#xff09;金字塔尺度间的图像信息补充 2&#xff09;目标检测与识别 3&#xff09;图像融合与拼接 4&#xff09;图像增强与去噪 5&#xff09;图像压缩与编码 二、用法解析 1、向下采样 1&#xff09;概念…

使用SQL语句查询MySQL数据表

6.1 创建单表基本查询 1&#xff0e;Select 语句的语法格式及其功能 &#xff08;1&#xff09;Select 语句的一般格式。 Select < 字段名称或表达式列表 > From < 数据表名称或视图名称 > [ Where < 条件表达式 > ] [ Group By < 分组的字段名称…

xss-labs-master通关教程

一.level1 先来进行一下代码审计 <?php ini_set("display_errors", 0);//关闭错误显示 $str $_GET["name"]; //接受URL来的get形式的name传参 echo "<h2 aligncenter>欢迎用户".$str."</h2>";//在网页输出&#x…

STM32 之 SDRAM 详解

目录 前言 一、SDRAM 简介 二、SDRAM的组成原理 2.1存储单元阵列 2.1.1地址译码 2.1.2存储电容 2.2控制逻辑 2.2.1时钟同步 2.2.2命令解码 2.2.3模式寄存器 2.3数据输入 / 输出缓冲 2.3.1数据总线 2.3.2数据锁存 2.4刷新电路 2.4.1自动刷新 2.4.2自刷新 三、S…

面试的一些小小经验

无论何时&#xff0c;找到合适的满意的工作&#xff08;距离住处的地理位置&#xff0c;薪资&#xff0c;工作氛围&#xff09;并不是一件容易的事情。个人能力与职位的适配性永远是有误差的客观存在。 十全十美难得&#xff0c;满足个人的个体化优先级才是客观的存在。 1.投简…

Gitlab修改已push的历史commit信息

文章目录 一、需求 二、思路 三、修改过程 四、注意 五、参考链接 一、需求 项目组结合使用JIRA和Gitlab进行项目开发。其中&#xff0c;JIRA用于管理开发任务(每个任务都存在一个JIRA_ID)&#xff0c;Gitlab用于进行代码版本管理。每次代码提交时&#xff0c;commit mes…