Rust 集合与字符串
时间:2026-08-20 22:20:32 179浏览 收藏
集合(Collection)是数据结构中最普遍的数据存放形式,Rust 标准库中提供了丰富的集合类型帮助开发者处理数据结构的操作。

向量
向量(Vector)是一个存放多值的单数据结构,该结构将相同类型的值线性的存放在内存中。
向量是线性表,在 Rust 中的表示是 Vec
向量的使用方式类似于列表(List),我们可以通过这种方式创建指定类型的向量:
let vector: Vec = Vec::new(); // 创建类型为 i32 的空向量
let vector = vec![1, 2, 4, 8]; // 通过数组创建向量 我们使用线性表常常会用到追加的操作,但是追加和栈的 push 操作本质是一样的,所以向量只有 push 方法来追加单个元素:
实例
fn main() {
let mut vector = vec![1, 2, 4, 8];
vector.push(16);
vector.push(32);
vector.push(64);
println!("{:?}", vector);
}
运行结果:
[1, 2, 4, 8, 16, 32, 64]append 方法用于将一个向量拼接到另一个向量的尾部:
实例
fn main() {
let mut v1: Vec = vec![1, 2, 4, 8];
let mut v2: Vec = vec![16, 32, 64];
v1.append(&mut v2);
println!("{:?}", v1);
}
运行结果:
[1, 2, 4, 8, 16, 32, 64]
get 方法用于取出向量中的值:
实例
fn main() {
let mut v = vec![1, 2, 4, 8];
println!("{}", match v.get(0) {
Some(value) => value.to_string(),
None => "None".to_string()
});
}
运行结果:
1因为向量的长度无法从逻辑上推断,get 方法无法保证一定取到值,所以 get 方法的返回值是 Option 枚举类,有可能为空。
这是一种安全的取值方法,但是书写起来有些麻烦。如果你能够保证取值的下标不会超出向量下标取值范围,你也可以使用数组取值语法:
实例
fn main() {
let v = vec![1, 2, 4, 8];
println!("{}", v[1]);
}
运行结果:
2但如果我们尝试获取 v[4] ,那么向量会返回错误。
遍历向量:
实例
fn main() {
let v = vec![100, 32, 57];
for i in &v {
println!("{}", i);
}
}
运行结果:
100
32
57如果遍历过程中需要更改变量的值:
实例
fn main() {
let mut v = vec![100, 32, 57];
for i in &mut v {
*i += 50;
}
}
字符串
字符串类(String)到本章为止已经使用了很多,所以有很多的方法已经被读者熟知。本章主要介绍字符串的方法和 UTF-8 性质。
新建字符串:
let string = String::new();
基础类型转换成字符串:
let one = 1.to_string(); // 整数到字符串
let float = 1.3.to_string(); // 浮点数到字符串
let slice = "slice".to_string(); // 字符串切片到字符串
包含 UTF-8 字符的字符串:
let hello = String::from("السلام عليكم");
let hello = String::from("Dobrý den");
let hello = String::from("Hello");
let hello = String::from("שָׁלוֹם");
let hello = String::from("नमस्ते");
let hello = String::from("こんにちは");
let hello = String::from("안녕하세요");
let hello = String::from("你好");
let hello = String::from("Olá");
let hello = String::from("Здравствуйте");
let hello = String::from("Hola");
字符串追加:
let mut s = String::from("run");
s.push_str("oob"); // 追加字符串切片
s.push('!'); // 追加字符
用 + 号拼接字符串:
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2;
这个语法也可以包含字符串切片:
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = s1 + "-" + &s2 + "-" + &s3;
使用 format! 宏:
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = format!("{}-{}-{}", s1, s2, s3);
字符串长度:
let s = "hello";
let len = s.len();
这里 len 的值是 5。
let s = "你好";
let len = s.len();
这里的 len 值是 6。原因不复杂:中文采用 UTF-8 编码,一个字符通常占 3 个字节,因此总长度就是 6。要注意的是,在 Rust 里这拿到的是字节长度,而不是“字符个数”。如果要统计真正的字符数量,就得先把字符串转换成字符集合:
let s = "hello你好";
let len = s.chars().count();这里 len 的值是 7,因为一共有 7 个字符。统计字符的速度比统计数据长度的速度慢得多。
遍历字符串:
实例
fn main() {
let s = String::from("hello中文");
for c in s.chars() {
println!("{}", c);
}
}
运行结果:
h
e
l
l
o
中
文
从字符串中取单个字符:
实例
fn main() {
let s = String::from("EN中文");
let a = s.chars().nth(2);
println!("{:?}", a);
}
运行结果:
Some('中')
注意:nth 函数是从迭代器中取出某值的方法,请不要在遍历中这样使用!因为 UTF-8 每个字符的长度不一定相等!
如果想截取字符串字串:实例
fn main() {
let s = String::from("EN中文");
let sub = &s[0..2];
println!("{}", sub);
}
运行结果:
EN但是请注意此用法有可能肢解一个 UTF-8 字符!那样会报错:
实例
fn main() {
let s = String::from("EN中文");
let sub = &s[0..3];
println!("{}", sub);
}
运行结果:
thread 'main' panicked at 'byte index 3 is not a char boundary; it is inside '中' (bytes 2..5) of `EN中文`', srclibcorestrmod.rs:2069:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
映射表
映射表(Map)在其他语言中广泛存在。其中应用最普遍的就是键值散列映射表(Hash Map)。
新建一个散列值映射表:
实例
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("color", "red");
map.insert("size", "10 m^2");
println!("{}", map.get("color").unwrap());
}
注意:这里没有声明散列表的泛型,是因为 Rust 的自动判断类型机制。
运行结果:
red
insert 方法和 get 方法是映射表最常用的两个方法。
映射表支持迭代器:
实例
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("color", "red");
map.insert("size", "10 m^2");
for p in map.iter() {
println!("{:?}", p);
}
}
运行结果:
("color", "red")
("size", "10 m^2")
迭代元素是表示键值对的元组。
Rust 里的映射表确实是个很顺手的数据结构。用 insert 方法新增键值对时,有个特性得先知道:一旦遇到相同的键,原来的值会被新值直接覆盖。那如果想做得更稳妥一点,只在某个键当前还不存在时才插入,也就是所谓“安全地插入”,可以这样写:
map.entry("color").or_insert("red");这句话的意思是如果没有键为 "color" 的键值对就添加它并设定值为 "red",否则将跳过。
在已经确定有某个键的情况下如果想直接修改对应的值,有更快的办法:
实例
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert(1, "a");
if let Some(x) = map.get_mut(&1) {
*x = "b";
}
} -
415 收藏
-
269 收藏
-
309 收藏
-
444 收藏
-
306 收藏
-
311 收藏
-
297 收藏
-
445 收藏
-
445 收藏
-
452 收藏
-
129 收藏
-
496 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习