八、标准库 - 常用集合类型
Published on
Vec
Vec是长度可变的数组,它在堆上分配空间,且能自动进行内存管理,类似于C++的std::vector。一个Vec包含3个参数:
- 数据指针
- 长度
- 容量
// 建立空Vec
let v: Vec<i32> = Vec::new();
// 使用初始值建立Vec
let v = vec![1, 2, 3];
// 添加值
v.push(4);
// 获取值
let third: &i32 = &v[2];
let third: Option<&i32> = v.get(2);
// 迭代值
for i in &v {
println!("{i}");
}
for i in &mut v {
*i += 50;
}
String
String是在堆上分配空间的动态字符串类型(区别于内置静态字符串类型&str),类似于C++的std::string。String底层存储使用Vec<u8>类型,但是保证总是有效的UTF8编码字符串。因此String中每个字符的大小不一致,需要小心使用。
// 建立空String
let mut s = String::new();
// 将&str转换为String
let s = "initial contents".to_string();
let s = String::from("initial contents");
// 追加内容
let mut s = String::from("foo");
s.push_str("bar");
// 使用+操作符拼接
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2;
// 使用format宏格式化
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = format!("{s1}-{s2}-{s3}");
// 切片。String不支持索引,如hello[0],但是支持切片。由于每个字符长度不一,因此需要额外注意
let s = &hello[0..4];
// 迭代所有字符
for c in "Зд".chars() {
println!("{c}");
}
// 迭代所有字节
for b in "Зд".bytes() {
println!("{b}");
}
HashMap
HashMap用于储存键-值对,类似于C++的std::map。
// 建立空HashMap
let mut scores = HashMap::new();
// 添加值/覆盖值
scores.insert(String::from("Blue"), 10);
// 根据键获取值
let team_name = String::from("Blue");
let score = scores.get(&team_name).copied().unwrap_or(0);
// 迭代键-值对
for (key, value) in &scores {
println!("{key}: {value}");
}
// 获取entry,根据entry可进一步进行不同的操作
let entry = scores.entry(String::from("Yellow"));
自定义键类型
可以使用任何实现了Eq与Hash特性的类型作为HashMap的键类型。
HashSet
HashSet<T>实际上是HashMap<T, ()>的包装器,用于存储不重复的元素。它有4个基本操作(全部返回迭代器):
- union:获取两个集合中的全部不同元素
- difference:获取在第一个集合中,但不在第二个集合中的元素
- intersection:获取同时在两个集合中的元素
- symmetric_difference:获取在一个集合中,但不同时在两个集合中的元素