阅读量:0
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) }