Common Collections
Vector
创建Vector
let x: Vec<i32> = Vec::new();// 创建Vector
// Vector<T> 中类型一样
// 可以显示声明 T 类型, 也可以编译器推断出 type
// 使用宏 vec! 来创建初始Vec<T>
let x = vec![1, 2, 3];
添加元素
// 添加元素
let mut v = Vec::new();
v.push(1);
v.push(2);
for x in v.iter() {
println!("{}", x);
}
删除Vector
当 Vector 离开作用域时会被删除
访问 Vector 中的元素
1.索引 data_name[index]
2.get data_name.get(index)
let x = vec![1, 2, 3, 4];
println!("{}", x[3]);
// v.get(index) 返回 Option<T>
match x.get(3) {
Some(val) => println!("{}", val),
None => println!("index out of bound"),
};
当 index 超出范围时
data_name[index] 会造成 panic
data_name.get(index) 会返回 None
Ownership
let mut v = vec![1, 2, 3, 4, 5];
let first = &v[0];
v.push(6);
println!("{}", first);
// cannot borrow `v` as mutable because it is also borrowed as immutable
记得Ownership 的特性吗? 不能同时有可变引用,和不可变引用
first 已经对 v 不可变引用, push 就不能操作了
可变引用的示例
let mut v = vec![1, 2, 3, 4, 5];
for i in &mut v {
*i += 1;
}
for i in v.iter() {
println!("{}", i);
}
Vector + enum
Vector + enum 可以实现 Vector 存不同类型
enum Kind {
int(i32),
double(f64),
string(String),
}
let x = vec![Kind::int(1), Kind::double(1.0), Kind::string(String::from("2024"))];
// enum 中的所有类型必须明确,这样编译器才可以确定大小
// 也可用 trait 超出本节范围,暂时不提
String
创建 String
let mut x = String::new();
let y = String::from("ABC");
添加元素
x.push('A');
x.push_str("ABC");
x += "A";// str 类型
x += &y;// 采用&String
println!("{}", x);// AABCA
println!("{}", y);// OwnerShip 不变
to String
// type -> String
// String::from();
// str_data_name.to_string();
let x = String::from("2024");// str -> String
let y = "2024".to_string();// str -> String
let z = 1;
let s = z.to_string();// i32 -> String
字符串拼接 +
let s1 = String::from("20");
let s2 = String::from("24");
let s3 = s1 + &s2;// 注意只有第一个不用& 等价于把&String -> &str
// println!("{}", s1);// Error! borrow of moved value: `s1`
println!("{}", s2);// right
println!("{}", s3);// right
format!
format! 拼接字符串 不会获得String的所有权
let s1 = String::from("20");
let s2 = String::from("24");
let s3 = format!("{}{}", s1, s2);
println!("{}", s1);// right
println!("{}", s2);// right
println!("{}", s3);// right
特性
String 不支持 [index] 访问元素
String len() 方法返回的是字节数,一般一个字母是一个字节
let x = String::from("SCUT");
let y = String::from("华工");
println!("{} {}", x.len(), y.len());// 输出 4 6 // 汉字有些占 2 字节, 有些占 3 字节
回到字符串切片
// 字符串切片只能沿着 char 边界切
// 比如 华 占两个字节,对中间切会造成 panic
let s = &y[0..1];
println!("{}", s);
// byte index 1 is not a char boundary; it is inside '华' (bytes 0..3) of `华工`
遍历
遍历 String
chars() 从字符角度
bytes() 从字节角度
for x in y.chars() {
println!("{}", x);
}
/*
华
工
*/
for x in y.bytes() {
println!("{}", x);
}
/*
229
141
142
229
183
165
*/
// Error!
for x in y {
}// 没有 iter
HashMap
数据在 heap 上
不在 Prelude 中
同一个 HashMap 中 K 类型必须一样
创建
let mut x: HashMap<String, i32> = HashMap::new();
可以显示指明也可以编译器推断
添加元素
insert
方法,其返回 Option<T>
x.insert(String::from("SCUT"), 2024);
// If the map did not have this key present, None is returned.
// If the map did have this key present, the value is updated, and the old value is returned.
访问元素
get
方法, 返回 Option<T>
let mut map = HashMap::new();
let k = String::from("SCUT");
match map.get(&k) {
Some(x) => println!("{}", x),
None => println!("None"),
};
更新 HashMap
// insert 插入时,如果对应的 key 存在,将替换对应的 val
检查 key
contains_key
方法 返回 bool
if map.contains_key(&k) {
println!("YES");
}
entry
方法 返回 enum Entry : 代表值是否存在
or_insert()
如果 key 存在 返回 val 的可变引用
如果 key 不存在 插入后返回其可变引用
let e = map.entry(&k);
e.or_insert(&v);
// 链式调用
let e = map.entry(&k).or_insert(&v);
遍历
for (k, v) in &map {
println!("{} {}", k, v);
}
Ownership
对于实现了 copy trait 的类型,值会被复制到 HahaMap
对于未实现 copy trait 的类型,其所有权会交给 HashMap
let mut map = HashMap::new();
let k = String::from("SCUT");
let v = String::from("2024");
map.insert(k, v);
println!("{} {}", k, v);// Error!
// move occurs because `v` has type `String`, which does not implement the `Copy` trait
let mut map: HashMap<&String, &String> = HashMap::new();
let k = String::from("SCUT");
let v = String::from("2024");
map.insert(&k, &v);// &String 形式
println!("{} {}", k, v);// correct
// 在 HashMap 有效期间, 被引用的值必须保持有效