【Rust】008
【Rust】008
Vec<T>
1、引入
在Java中,List
接口是一个非常常用的数据结构接口,它定义了一组可以用于操作有序集合的方法。ArrayList
是List
接口的一个常见实现,提供了动态数组的功能。通过ArrayList
,我们可以方便地进行元素的添加、删除和访问。
如果你熟悉Java的ArrayList
,那么理解Rust的Vec<T>
会相对容易。以下是从List
和ArrayList
引出Rust的Vec<T>
的一些要点:
- 动态数组的概念:
- 在Java中,
ArrayList
实现了List
接口,是一个可以动态调整大小的数组。它通过在内部维护一个可变大小的数组来实现这一点,并在需要时自动扩展。 - 在Rust中,
Vec<T>
是一个动态数组,类似于Java的ArrayList
。它可以根据需要动态扩展和缩小,存储同一类型的元素。
- 在Java中,
- 创建和初始化:
- 在Java中,创建一个
ArrayList
通常是通过new ArrayList<>()
。 - 在Rust中,创建一个
Vec
可以通过Vec::new()
或者使用宏vec![]
来初始化。
- 在Java中,创建一个
- 添加元素:
ArrayList
使用add()
方法来添加元素。Vec<T>
使用push()
方法来添加元素。
- 访问元素:
- 在
ArrayList
中,可以使用get(index)
方法来访问元素。 - 在
Vec<T>
中,可以使用索引语法vec[index]
来访问元素。
- 在
- 删除元素:
ArrayList
提供了remove(index)
方法来删除指定位置的元素。Vec<T>
提供了remove(index)
方法来删除指定位置的元素。
- 性能和内存管理:
ArrayList
依赖于Java的垃圾回收机制来管理内存。Vec<T>
则利用Rust的所有权系统来自动管理内存,确保在不再需要时自动释放。
- 线程安全:
ArrayList
不是线程安全的,但Java提供了其他线程安全的集合类。Vec<T>
也不是线程安全的,需要在多线程环境中使用同步机制来保护。
2、三种常见初始化方式
第一种:初始化一个长度为零且不进行内存分配的数组
代码语言:javascript代码运行次数:0运行复制这种方式使用
Vec::new()
方法。此方法创建一个空的Vec
,长度为零,并且初始时不分配额外的内存空间。 场景:这种方式适合在不确定具体容量需求的情况下使用,Rust会在需要时自动分配内存。
let v: Vec<String> = Vec::new();
第二种:初始化一个长度为零但提前分配好16个元素大小内存的数组
代码语言:javascript代码运行次数:0运行复制使用
Vec::with_capacity(16)
方法。这会创建一个空的Vec
,长度为零,但预先分配了可以容纳16个元素的内存。 场景:这种方式适合当你知道大致需要多少容量时使用,可以减少内存重新分配的开销,提高性能。
let mut v: Vec<String> = Vec::with_capacity(16);
第三种:使用vec!
宏创建数组并初始化元素
代码语言:javascript代码运行次数:0运行复制
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 中的字符串类型:
&str
和String
:
其它写法
代码语言:javascript代码运行次数:0运行复制Rust 有类型推导的能力
fn this_also_works() {
let mut v = Vec::new(); // 这里可以先不指定类型
v.push("str"); // 在这里,编译器会通过元素的类型确定 v 的类型,为 Vec<&str>
}
代码语言:javascript代码运行次数:0运行复制直接指定泛型类型
fn this_also_works2() {
let _ = Vec::<String>::new();
}
、添加、访问与修改数组元素
代码语言:javascript代码运行次数:0运行复制通过
.push
方法添加一个元素,可以通过下标[i]
的方式访问数组元素,如果i
超过数组长度,程序直接 panic。
fn get_by_index() {
let mut v = Vec::new();
// 通过`.push`方法添加一个元素
v.push(1);
v.push(2);
println!("{}", v[1]); // 输出 2
println!("{}", v[2]); // 这里程序会直接退出
}
代码语言:javascript代码运行次数:0运行复制那有没有不会 panic 的方式呢?有的,我们可以通过
.get
的方法,该函数的返回的是Option<&T>
,如果数组越界了,会返回 one。(不过因为会多一次检查,这种方式性能会差一点)。
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)); // 输出 one
}
代码语言:javascript代码运行次数:0运行复制通过下标修改数组元素
fn modify_by_index() {
let mut v = Vec::new();
v.push(1);
v.push(2);
v[0] = 100;
println!("{}", v[0]); // 会输出 100
}
4、删除元素
代码语言:javascript代码运行次数:0运行复制可以通
.pop
将数组的最后一个元素弹出来,如果数组为空,则返回 one
fn pop_elem() {
let mut v = vec!["Hello", "Rust"];
println!("{:?}", v.pop()); // 输出 Some("Rust")
}
代码语言:javascript代码运行次数:0运行复制还可以通过
.remove
移出指定下标的元素,且该方法会保持数组元素原来的顺序。也可以通过.swap_remove
来移除,不过这个会将数组最后一个元素移到被删除的位置,不能保持数组元素原来的顺序。(第二种方式好奇怪!)。
fn main() {
let mut v = vec!["1", "2", "", "4", "5"];
v.remove(1);
println!("{:?}", v); // ["1", "", "4", "5"]
v.swap_remove(1);
println!("{:?}", v); // ["1", "5", "4"]
}
5、遍历元素
代码语言:javascript代码运行次数:0运行复制遍历元素要特别注意所有权,
for
是会消耗变量的。
fn will_cume_v() {
let v = vec!["Hello", "World"];
for elem in v {
println!("{elem}");
}
println!("{:?}", v); // 这行将会报错,因为我们在第三行的 for 已经将 v 给消耗掉了
}
代码语言:javascript代码运行次数:0运行复制为了避免被消耗掉
v
,我们可以对v
取引用,这样拿到的elem
则会是&T
类型:
fn willnot_cume_v() {
let v = vec!["Hello", "World"];
for elem in &v {
println!("{elem}");
}
println!("{:?}", v); // 这行会正常输出
}
代码语言:javascript代码运行次数:0运行复制如果想对元素进行修改,可以对
v
取可变引用
fn modify_elem() {
let mut v = vec!["Hello", "World"];
for elem in &mut v {
// *elem 注意这个写法
*elem = "elem"
}
println!("{:?}", v); // 这行会输出 ["elem", "elem"]
}
1、引入
如果你熟悉 Java 的 HashMap
,并且想要在 Rust 中使用类似的功能,以下是一些关键点和步骤,可以帮助你顺利过渡:
创建 HashMap:
在 Java 中,你通常会这样创建一个 HashMap
:
Map<String, Integer> map = new HashMap<>();
在 Rust 中,你需要引入标准库的集合模块,然后创建一个 HashMap
:
use std::collecti::HashMap;
let mut map = HashMap::new();
插入键值对:
Java 中的插入操作使用 put
方法:
map.put("key", 1);
Rust 中使用 insert
方法:
map.insert("key", 1);
访问值:
在 Java 中,你可以使用 get
方法来访问值:
Integer value = map.get("key");
Rust 中的 get
方法返回一个 Option
,因为键可能不存在:
if let Some(&value) = map.get("key") {
println!("Value: {}", value);
}
迭代:
Java 中可以使用 entrySet
来迭代:
for (Map.Entry<String, Integer> entry : ()) {
println(entry.getKey() + ": " + entry.getValue());
}
在 Rust 中,你可以使用 iter
方法:
for (key, value) in &map {
println!("{}: {}", key, value);
}
删除键值对:
Java 使用 remove
方法:
map.remove("key");
Rust 也使用 remove
方法:
map.remove("key");
检查键的存在性:
Java 中可以使用 containsKey
方法:
if (("key")) {
// do something
}
在 Rust 中,你可以使用 contains_key
方法:
if _key("key") {
// do something
}
注意事项:
- Rust 中的
HashMap
默认不是线程安全的。如果你需要在多线程环境中使用,可以考虑使用Mutex
或RwLock
来保护它。 - Rust 的
HashMap
使用泛型,确保在编译时进行类型检查,避免了许多运行时错误。
2、两种常见初始化方式
第一种:使用 new
代码语言:javascript代码运行次数:0运行复制
HashMap::new()
创建一个空的HashMap
,默认情况下具有一定的初始容量,但具体的容量可能会根据实现和编译器的不同而有所变化。
use std::collecti::HashMap;
let mut map = HashMap::new();
第二种:使用 with_capacity
代码语言:javascript代码运行次数:0运行复制
HashMap::with_capacity(capacity)
创建一个具有指定初始容量的HashMap
。这对于知道大概要插入多少元素的情况特别有用,可以减少在插入过程中可能发生的内存重新分配。
use std::collecti::HashMap;
let mut map = HashMap::with_capacity(10);
、对元素的增删改查与遍历
代码语言:javascript代码运行次数:0运行复制use std::collecti::HashMap;
fn main() {
// 创建一个新的 HashMap
let mut map = HashMap::new();
// ## 1、添加元素
// 使用 insert 方法添加键值对
map.insert("apple", );
map.insert("banana", 5);
map.insert("orange", 2);
// 此时,map 包含了三个键值对:("apple", ), ("banana", 5), ("orange", 2)
// ## 2、访问元素
// 使用 get 方法访问元素,get 返回的是 Option<&V>
if let Some(&count) = map.get("apple") {
println!("apple 的数量是:{}", count);
} else {
println!("apple 不存在于 map 中");
}
// 如果键存在,打印其对应的值;否则,说明键不存在
// ## 、修改元素
// 直接使用 insert 方法可以修改元素的值
map.insert("banana", 10);
// 现在 "banana" 对应的值被修改为 10
// 另一种修改方法是使用 entry API
("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去遍历。不过相应的,遍历元素的类型也会变成引用。
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2024-09-10,如有侵权请联系 cloudcommunity@tencent 删除集合内存数组rust遍历 #感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
下一篇:【Rust】007
推荐阅读
留言与评论(共有 7 条评论) |
本站网友 中考复读 | 21分钟前 发表 |
v[1]); // 输出 2 println!("{}" | |
本站网友 牛奶的功效和作用 | 23分钟前 发表 |
本站网友 怡思丁 | 29分钟前 发表 |
<String> | |
本站网友 虞城教育网 | 18分钟前 发表 |
V>1 | |
本站网友 狗鞭 | 23分钟前 发表 |
它可以根据需要动态扩展和缩小 | |
本站网友 空客310 | 19分钟前 发表 |
{}" |