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 代码。

相关推荐
亿坊电商3 分钟前
PHP框架 vs 原生开发:移动应用后端开发实战对比!
开发语言·php
k***85848 分钟前
【SpringBoot】【log】 自定义logback日志配置
android·前端·后端
S***q19219 分钟前
Kotlin内联函数优化
android·开发语言·kotlin
在路上看风景24 分钟前
2.3 C#装箱和拆箱
开发语言·c#
Source.Liu24 分钟前
【Chrono库】NaiveTime - Serde 序列化实现(naive/time/serde.rs)
rust·time
C语言小火车31 分钟前
C/C++ 指针全面解析:从基础到进阶的终极指南
c语言·开发语言·c++·指针
g***B73838 分钟前
Python数据分析案例
开发语言·python·数据分析
小灰灰搞电子38 分钟前
Qt 使用打印机详解
开发语言·qt
lqj_本人39 分钟前
鸿蒙Qt混合开发:NAPI数据转换的深坑与避雷指南
开发语言·qt
天蝎没有心40 分钟前
QT-对话框
开发语言·qt