赞
踩
集合这个概念和数学的本质是一样的,就是一群类似的数据放到一起。在Rust中主要有三种集合:
1、字符串
这个应该不用过多解释,就是一串字符组合在一起。
2、Vec
学过c++的STL的同学可能一下子就会明白,一个动态数组,平坦空间上的。
3、HashMap
这个其实是两个数据结构Hash和Map组合在一起。
1、Vec的应用
vec是一个动态增删数据的数组,平均的时间复杂度是O(1)。换句话说,它可以随机的访问数据内容;同时,对首尾的写操作也是O(1)。看下面的例程:
//new方式声明 let mut v1: Vec<i32> = Vec::new(); //宏方式 let v: Vec<i32> = vec![]; // 以下语句相当于: // let mut temp = Vec::new(); // temp.push(1); // temp.push(2); // temp.push(3); // let v = temp; let v = vec![1, 2, 3]; let v = vec![0; 10]; //注意分号,这句话声明了一个 内容为10个0的动态数组 //迭代器声明 let v: Vec<_> = (1..5).collect(); //直接访问 let a = vec![1, 2, 3]; assert_eq!(a[1usize], 2); //安全访问 let v =vec![1, 2, 3]; assert_eq!(v.get(1), Some(&2)); assert_eq!(v.get(3), None); //迭代器访问 let v = vec![1, 2, 3]; for i in &v { .. } // 获得引用 for i in &mut v { .. } // 获得可变引用 for i in v { .. } // 获得所有权,注意此时Vec的属主将会被转移!!
再看一个例程:
use std::time; fn push_1m(v: &mut Vec<usize>, total: usize) { let e = time::SystemTime::now(); for i in 1..total { v.push(i); } let ed = time::SystemTime::now(); println!("time spend: {:?}", ed.duration_since(e).unwrap()); } fn main() { let mut v: Vec<usize> = vec![]; push_1m(&mut v, 5_000_000); let mut v: Vec<usize> = vec![]; v.reserve(5_000_000); push_1m(&mut v, 5_000_000); }
这个vec的缺点和STL中的没啥不同,都是内存的冗余消耗和复制的时间消耗。
2、HashMap
这个集合在td::collections下,有一个o(1)的查询方法。它要求Key必须是可比较的,注意,如果自定义一个Key,需要处理一下。
use std::collections::HashMap; // 声明 let mut come_from = HashMap::new(); // 插入 come_from.insert("WaySLOG", "HeBei"); come_from.insert("Marisa", "U.S."); come_from.insert("Mike", "HuoGuo"); // 查找key if !come_from.contains_key("elton") { println!("Oh, 我们查到了{}个人,但是可怜的Elton猫还是无家可归", come_from.len()); } // 根据key删除元素 come_from.remove("Mike"); println!("Mike猫的家乡不是火锅!不是火锅!不是火锅!虽然好吃!"); // 利用get的返回判断元素是否存在 let who = ["MoGu", "Marisa"]; for person in &who { match come_from.get(person) { Some(location) => println!("{} 来自: {}", person, location), None => println!("{} 也无家可归啊.", person), } } // 遍历输出 println!("那么,所有人呢?"); for (name, location) in &come_from { println!("{}来自: {}", name, location); }
对存在Key的处理,Rust提供了entry这种处理方式:
use std::collections::HashMap;
let mut letters = HashMap::new();
for ch in "a short treatise on fungi".chars() {
let counter = letters.entry(ch).or_insert(0);
*counter += 1;
}
assert_eq!(letters[&'s'], 2);
assert_eq!(letters[&'t'], 3);
assert_eq!(letters[&'u'], 1);
assert_eq!(letters.get(&'y'), None);
它的优势就在于,编程者不用再写一个丑陋的判断语句判断是否此数据已经存在于HashMap中,而自动交给entry().or_insert来处理。
3、字符串
字符串几乎所有的语言都处理,只有C清高对些不屑一顾。rust中字符串默认是以UTF-8编码的。
let mut s = String::new();
let data = "my strings";
let s = data.to_string();
// 直接赋值:
let s = "my strings".to_string();
//from赋值
let ss = String::from("my strings");
字符串的几乎所有想到的操作Rust中都提供了,包括slice:
//追加字符串 fn main() { let mut s = String::from("add "); s.push_str(" one"); } //拼接字符串 fn main() { let s1 = String::from("Hello, "); let s2 = String::from("world!"); let s3 = s1 + &s2; // 注意 s1 被移动了,不能继续使用 } //拼接字符串2 fn main() { let s11 = String::from("ddc"); let s12 = String::from("erc"); let s13 = String::from("ghu"); let s = format!("{}-{}-{}", s11, s12, s13); } //字符串的slice fn main() { let hello = "qswertyuihu"; let s = &hello[0..4]; //let s = &hello[0..1] ;//panic 一定要小心 } //遍历 fn main() { for c in "asdfgh".chars() { println!("{}", c); } for b in "asdfgh".bytes() { println!("{}", b); } }
有所不同的是,在Rust中不允许索引字符串,比如像c++中直接通过下标或者指针来访问具体索引上的字符串,是编译无法通过的。知易行难啊,不容易。
对于类似于STL的这种集合的操作,原则上是越多越方便,越简单越方便。同时,这些集合的底层实现和跨平台的效率却更是体现了Rust语言本身的开发者的能力。一个好的语言,一定会有一个尽量兼顾各方的库和其它结构,这既是一个对上层友好的优点,也是对语言开发者本身不友好的缺点,而且,这还可能造成其在某个特点平台或者特定场合下的效率的不够高。这也是所有这种框架和库的本身的一种无奈,既想要面面具到,又无法面面具到。其实在前面就提到过,Rust本身在这方面其实就很有果决的勇气,删除了很多东西,这也是Rust在社区广受好评的一个重要因素。
正所谓,有得就有失,有失就有得。努力吧,归来的少年!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。