Rust入门开发之Rust 集合:灵活的数据容器

前言

在 Rust 编程世界中,集合是一种强大的数据结构,用于存储多个值。与数组和元组不同,集合通常存储在堆上,其大小可以在运行时动态改变。Rust 的标准库提供了多种集合类型,每种类型都有其独特的用途和优势,它们遵循严格的所有权和借用规则,确保了内存安全。接下来,让我们深入了解 Rust 中常用的集合类型及其使用方法。

一、Vec:动态数组

Vec,即向量(vector),是 Rust 中最常用的集合类型之一,它表示一个可变长度的、同类型元素的动态数组,在内存中有三个字段:长度、容量和一个指向堆上分配的缓冲区的指针。Vec可以根据需要自动调整大小,适合用于存储数量不确定的数据。

1、创建 Vec

可以使用Vec::new()函数创建一个空的Vec,也可以使用vec!宏创建带有初始值的Vec

rust 复制代码
// 创建一个空的Vec<i32>
let mut v1: Vec<i32> = Vec::new();
// 使用vec!宏创建带有初始值的Vec<i32>
let v2 = vec![1, 2, 3];

2、访问元素

可以使用索引或get方法来访问Vec中的元素。使用索引访问时,如果索引超出范围,程序会发生panic;而get方法则会返回一个Option<&T>,如果索引无效则返回None,从而避免了panic

rust 复制代码
let v = vec![1, 2, 3];
// 使用索引访问元素
let first = v[0];
// 使用get方法访问元素
let second: Option<&i32> = v.get(1);
match second {
    Some(value) => println!("The second element is {}", value),
    None => println!("No second element found"),
}

3、修改 Vec

可以使用push方法向Vec中添加元素,使用pop方法移除并返回最后一个元素,使用insert方法在指定位置插入元素,使用remove方法移除指定位置的元素。

rust 复制代码
let mut v = vec![1, 2, 3];
// 向Vec中添加元素
v.push(4);
// 移除并返回最后一个元素
let last = v.pop();
match last {
    Some(value) => println!("The last element was {}", value),
    None => println!("The Vec is empty"),
}
// 在指定位置插入元素
v.insert(1, 99);
// 移除指定位置的元素
let removed = v.remove(2);
println!("Removed element: {}", removed);

4、遍历 Vec

可以使用for循环遍历Vec中的元素,也可以使用iter方法返回一个迭代器,对元素进行更灵活的操作。

rust 复制代码
let v = vec![1, 2, 3];
// 使用for循环遍历
for element in &v {
    println!("{}", element);
}
// 使用iter方法遍历
v.iter().for_each(|x| println!("{}", x));

在所有权和借用方面,当一个Vec被赋值给另一个变量时,所有权会发生转移。例如:

rust 复制代码
let v1 = vec![1, 2, 3];
let v2 = v1; // v1的所有权转移给v2,此时v1不再有效

如果只想借用Vec中的元素,可以使用引用。不可变借用允许同时存在多个引用,用于读取元素:

rust 复制代码
let v = vec![1, 2, 3];
let ref1 = &v;
let ref2 = &v;
for element in ref1 {
    println!("{}", element);
}

可变借用则在同一时间只能有一个,用于修改元素:

rust 复制代码
let mut v = vec![1, 2, 3];
let mut_ref = &mut v;
mut_ref.push(4);

二、HashMap<K, V>:键值对存储

HashMap<K, V>是一种键值对存储的数据结构,它使用哈希函数来确定键的存储位置,从而实现快速的插入、查找和删除操作,在处理大量数据时非常高效。其中,K是键的类型,V是值的类型,键必须实现EqHash trait。

1、创建 HashMap

可以使用HashMap::new()创建一个空的HashMap,也可以使用迭代器和collect方法创建带有初始值的HashMap

rust 复制代码
use std::collections::HashMap;
// 创建一个空的HashMap<String, i32>
let mut scores = HashMap::new();
// 使用迭代器和collect方法创建HashMap
let teams = vec![String::from("Blue"), String::from("Yellow")];
let initial_scores = vec![10, 50];
let scores: HashMap<_, _> = teams.into_iter().zip(initial_scores.into_iter()).collect();

2、插入键值对

使用insert方法向HashMap中插入键值对。

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

3、访问值

使用get方法通过键来访问HashMap中的值,get方法返回一个Option<&V>,如果键存在则返回Some(&value),否则返回None

rust 复制代码
let team_name = String::from("Blue");
let score: Option<&i32> = scores.get(&team_name);
match score {
    Some(value) => println!("The score of {} is {}", team_name, value),
    None => println!("No score found for {}", team_name),
}

4、修改 HashMap

如果插入的键已经存在,insert方法会覆盖原有的值;使用remove方法可以移除指定键的键值对。

rust 复制代码
// 更新键值对
scores.insert(String::from("Blue"), 20);
// 移除键值对
scores.remove(&String::from("Blue"));

5、遍历 HashMap

可以使用for循环遍历HashMap中的所有键值对。

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

三、HashSet:哈希集合

HashSet<T>是一种只存储唯一值的集合,它基于HashMap<T, ()>实现,每个元素作为HashMap的键,值为单元类型()HashSet的插入、删除和查找操作都非常快速,适用于需要快速判断元素是否存在的场景。

1、创建 HashSet

使用HashSet::new()创建一个空的HashSet,并使用insert方法添加元素。

rust 复制代码
use std::collections::HashSet;
let mut set = HashSet::new();
// 添加元素
set.insert(1);
set.insert(2);
set.insert(3);

2、检查元素存在

使用contains方法检查HashSet中是否包含某个元素。

rust 复制代码
if set.contains(&1) {
    println!("The set contains 1");
} else {
    println!("The set does not contain 1");
}

3、移除元素

使用remove方法从HashSet中移除元素。

rust 复制代码
// 移除元素
set.remove(&1);

4、遍历 HashSet

可以使用for循环遍历HashSet中的元素。

rust 复制代码
for element in &set {
    println!("{}", element);
}

四、总结

Rust 的集合类型为开发者提供了强大而灵活的数据存储和操作能力,能够满足各种不同的编程需求。通过合理运用VecHashMapHashSet等集合类型,可以编写出高效、安全且易维护的 Rust 代码。

相关推荐
小龙报8 小时前
《算法通关指南算法千题篇(5)--- 1.最长递增,2.交换瓶子,3.翻硬币》
c语言·开发语言·数据结构·c++·算法·学习方法·visual studio
今日说"法"8 小时前
Rust 线程安全性的基石:Send 与 Sync 特性解析
开发语言·后端·rust
报错小能手8 小时前
C++笔记(面向对象)定义虚函数规则 运行时多态原理
开发语言·c++·笔记
Cx330❀8 小时前
《C++ 多态》三大面向对象编程——多态:虚函数机制、重写规范与现代C++多态控制全概要
开发语言·数据结构·c++·算法·面试
seabirdssss9 小时前
JDK 11 环境正确,端口未被占用,但是运行 Tomcat 11 仍然闪退
java·开发语言·tomcat
Mr YiRan9 小时前
SYN关键字辨析,各种锁优缺点分析和面试题讲解
java·开发语言
IT_陈寒9 小时前
从2秒到200ms:我是如何用JavaScript优化页面加载速度的🚀
前端·人工智能·后端
Zhang青山9 小时前
028.爬虫专用浏览器-抓取#shadowRoot(closed)下
java·后端
bug攻城狮9 小时前
SpringBoot响应封装:Graceful Response vs 自定义通用响应类选型指南
java·spring boot·后端·http