rust 初探 – 常用的集合
Vector
存储在堆内存上的数据,运行时可以动态变大或者变小。
Vec 特性:
- 由标准库提供,可以存储多个相同类型的值,并且值在内存中连续存放
Vector 的创建
fn main() {
// Vec::new()
let v: Vec<i32> = Vec::new();
// 使用初始值创建,使用 vec! 宏
let v1 = vec![1,2,3];
}
更新 Vector
fn main() {
//这里不需要指明 vec 的类型,因为后面有 push 操作会自己推断出来
let mut v = Vec::new();
v.push(1);
}
删除 Vector
和其他的 struct 结构体一样,当 Vector 离开了作用域,就会被清理掉
如果涉及到引用会不一样。
读取 Vector 的元素
fn main() {
let v = vec![1,2,3,4,5];
let third = &v[2]; // 1. 使用索引,非法访问 panic
println!("{}", third);
match v.get(2) { // 2. get 方法,非法访问 返回 None
Some(third) => println!("get {}", third),
None => println!("not exist"),
}
}
所有权和借用规则
不能在同一作用域里,对一个值不能同时有可变和不可变的引用
//vec 中内存中是连续的,新增的时候可能会重新分配,所以直接不让这样操作
fn main() {
let mut v = vec![1,2,3,4,5];
let third = &v[2]; //不可变的
v.push(6); //mutable borrow occurs here
println!("{}", third);
}
遍历 Vector 的值
fn main() {
let mut v = vec![1,2,3,4,5];
for i in &mut v {
*i += 50;
}
for i in v {
println!("{}", i);
}
}
使用 enum 来存储多种数据类型
- enum 的变体可以附加不同类型的数据
- enum 的变体定义在同一个 enum 类型下
enum Cell {
Int(i32),
Float(f64),
Text(String),
}
// 因为类型不同,枚举的时候不好操作(很多个),需要使用到 trait 对象
fn main() {
//编译时就知道堆上要多大的内存,而且知道所有的可能情况,编译时可以做检查
let row = vec![
Cell::Int(3),
Cell::Float(10.1),
Cell::Text(String::from("text")),
];
}
字符串是什么
-
Rust 的核心语言层面,只有一个字符串类型:字符串切片 str(或&str)
-
字符串切片:对存储在其他地方、UTF-8编码的字符串的引用
- 字符串字面值:存储在二进制文件中,也是字符串切片
-
String 类型:
- 来自标准库而不是核心语言
- 可增长、可修改、可拥有
通常说的字符串是指?
String 和 &str
- 特性:utf-8 编码
其他类型的字符串
- OsString,OsStr,CString,Cstr
- 还有一些其他第三方库
创建一个新的字符串
String::new()//用于创建一个空的字符串,是可变的
to_string() //方法,可用于实现了 displag trait 的类型,包括字符串字面值
String::from() //函数,从字面值来创建字符串
更新 String
- push_str() 方法:字符串切片
fn main() {
let mut s1 = String::from("foo");
s1.push_str("bar");//- push_str() 方法:字符串切片
println!("{}", s1); // foobar
s1.push('b');//- push() 方法:单个字符
println!("{}", s1); // foobarb
}
-
- 操作符,拼接字符串
fn main() {
let s1 = String::from("foo");
let s2: String = String::from("bar");
let s3 = s1 + &s2;
//相当于 fn add(self, s: &str) -> String {}
//&String 强制转换成 &str,解引用强制转换(deref coercion),会保留 s2 的所有权
println!("{}", s3);
// println!("{}", s1);//error[E0382]: borrow of moved value: `s1`
// println!("{}", s2);
}
- format!:不会取得任意参数的所有权
use std::fmt::format;
fn main() {
let s1 = String::from("foo");
let s2: String = String::from("bar");
let s3: String = String::from("car");
// let s4 = s1 + "-" + &s2 + "-" + &s3;
// println!("{}", s4); //foo-bar-car
let s5 = format!("{}-{}-{}", s1, s2, s3);
println!("{}", s5);//foo-bar-car
}
内部表示
- String 是对 Vex 的包装
String::from("hola").len(); //4,返回字节数
// unicode 标量值
字节,标量值,字形簇
fn main() {
let w = "测试一下";
for b in w.bytes() {//字节
print!("{} ", b)//230 181 139 232 175 149 228 184 128 228 184 139
}
for b in w.chars() {//标量值
print!("{} ", b)// 测 试 一 下
}
}
访问 String
- 不支持按索引语法形式进行访问:
- 不同语言的字符串,其对应的字节数不同
- 索引操作应消耗一个常量时间(O(1)),而String 无法保证,需要遍历所有内容来确定有多少个合法的字符
切割 String
s = &hello[0..4]; //但是切割必须沿着字符的边界切割,否则会panic
HashMap<K, V>
- 键值对的形式存储数据
- 适合场景,通过 K (任何类型)来寻找数据,而不是通过索引
创建 HashMap
use std::collections::HashMap;
fn main() {
//创建 HashMap
let mut scores = HashMap::new();
scores.insert(String::from("bob"), 99); //会基于此推断 k,v的类型
// 不在 Prelude 中,所以需要添加 use
//2. collect()
let team = vec![String::from("a"), String::from("b")];
let t_scores = vec![10,12];
let hp: HashMap<_, _> = team.iter().zip(t_scores.iter()).collect();
// 需要指明 HashMap<_, _>
}
- 数据存储在 heap 上
- 同构的:一个 HashMap 中,所有 k 必须是同一类型,所有 v 必须是同一类型
HashMap 和所有权
- 对于实现了 Copy trait 的类型,值会被复制到 HashMap 中
- 对于拥有所有权的值(如 String),值会被移动,所有权会被转移给 HashMap
- 如果将值的引用插入到 HashMap,值本身不会移动 (被引用的值需要有效)
fn main() {
let name = String::from("key");
let value = String::from("value");
//创建 HashMap
let mut scores = HashMap::new();
// scores.insert(name, value);
// print!("{}:{}", name, value); // value borrowed here after move
scores.insert(&name, &value);
println!("{}:{}", name, value);//key:value
}
访问 HashMap
- get 方法,参数 K,返回 Option<&V>
use std::collections::HashMap;
fn main() {
//创建 HashMap
let mut scores = HashMap::new();
scores.insert(String::from("bob"), 90);
scores.insert(String::from("lili"), 100);
let name = String::from("bob");
let score = scores.get(&name);
match score {
Some(s) => println!("{}", s), // 90
None => println!("team not exist"),
};
}
遍历 HashMap
use std::collections::HashMap;
fn main() {
//创建 HashMap
let mut scores = HashMap::new();
scores.insert(String::from("bob"), 90);
scores.insert(String::from("lili"), 100);
for (k, v) in &scores {
println!("{}-{}", k, v)//lili-100 bob-90
}
}
更新 HashMap
- HashMap 大小可变,每个 K 只能对应一个 V
- 更新 HashMap 中的数据,已存在 K,或者不存在 K
use std::collections::HashMap;
fn main() {
//创建 HashMap
let mut scores = HashMap::new();
scores.insert(String::from("bob"), 90);
scores.insert(String::from("lili"), 100);
//1. 替换现有的 v,插入两个相同k,不同 v,前者会被后者替换
//2. 只在 K 不存在时,才插入 v
//使用 entry 方法,结合 or_insert
scores.entry(String::from("bob")).or_insert(80);
scores.entry(String::from("bob2")).or_insert(80);
println!("{:#?}", scores)
}
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » rust 初探 -- 常用的集合
发表评论 取消回复