什么是Collections
在 Rust 中,collections 是一组用于存储多个值的标准库数据结构。不同于数组和元组,collections 可以存储可变数量的数据。Rust 的标准库提供了几种常用的集合类型,每种类型都有其特定的用途和性能特点。
Vector - 向量
Vector
是一个泛型集合
Vec<T>
它是一组同一类型的元素的集合,类似于我们在其他语言中使用的可变长度的数组或列表, 这也是我们在实际编程中最常用的Collection类型。
当我们创建一个Vector
时, 我们需要在<>
内指定其中的元素类型:
let mut v: Vec<i32> = Vec::new();
创建了一个向量后, 我们就可以对其进行操作了,Vector
的行为跟栈比较类似,我们可以用push
函数将元素压入到的向量末尾:
let mut v: Vec<i32> = Vec::new();
v.push(2);
v.push(4);
v.push(6);
let x = v.pop(); // x的值为6
println!("{}", v[1]); // 输出4
而pop
函数则会移除向量末尾的元素并将其作为返回值返回。而且由于向量的元素是同一类型的,因此元素的大小是已知并固定的,在内存中也是彼此相邻的存储, 因此可以对其进行索引操作, 如果你的索引超出了向量的长度, Rust会触发panic
, 虽说会产生运行时错误,但总比随便从内存中捡个垃圾数据喂我们吃要好得多。
针对向量, Rust标准库中已经提供了很多基本操作,来满足我们对向量的操作需求,例如插入,删除,拆分,拼接,排序,去重,二叉搜索等。
向量宏 - vec!
通常在创建一个向量时,我们就已知它的部分值, Rust提供一个名为vec!
的宏, 注意首字母是小写, 这使得我们直接从字面值创建一个向量变得方便了很多,而不必一个一个的push
, 例如:
let mut v = vec![2, 4, 6];
HashMap - 哈希表
HashMap
也是一个很常用的集合类型,在其他一些语言中(如Python), 这被称为字典。它由一组键值对组成,并可以通过键访问值。
HashMap<K, V>
使用哈希表的意义在于我们能够在恒定的时间内按键对值进行增删改查。Rust 中, 一个HashMap
中的所有键的类型必须相同, 所有值的类型也必须相同, 且在声明它的时候就必须确定:
let mut h: HashMap<u8, bool> = HashMap::new();
上面的代码中初始化了一个键的类型为u8
, 值的类型为bool
的哈希表,下面就可以向哈希表中插入元素了:
let mut h: HashMap<u8, bool> = HashMap::new();
h.insert(5, true);
h.insert(6, false);
如果要删除某个元素,就用remove
函数:
let have_five = h.remove(&5).unwrap();
这会返回一个Option
的枚举类型(后面的章节再讨论枚举类型)。
Rust标准库中还提供了一系列的函数,可以获取哈希表中值的引用,获得哈希表的迭代器,迭代其中的键或值或键值对。
其他Collection类型
除了上述两种最常用的集合类型外, Rust中还有很多其他的集合类型,我们不一一详述,就只是走马观花的看一下吧。
VecDeque
: 使用一个环形的缓冲区来实现一个双端队列, 它可以高效的从前面和后面添加或删除元素, 但其他的操作效率都比普通的Vector
低;LinkedList
: 链表,它可以在列表中的任意点快速添加或删除一个元素, 但在其他的操作上,性能都较慢;HashSet
: 是集合(Set
) 的哈希实现, 比普通的Set
更高效的执行集合的各种操作;BinaryHeap
: 类似于一个优先级队列, 可以总是弹出队列中的最大值;BTreeMap
和BTreeSet
: 是用二叉树实现的映射和集合,在需要经常对映射或集合中的值进行排序操作时非常有用;
小结
本章介绍了常用的两种集合类型以及他们的用法,下一章我们将讨论Rust中的枚举类型 Enum。