天天看點

Rust從入門到精通12-集合

Rust 标準庫中還提供了一系列被稱為 集合(collections)的資料結構,類似于JDK中 ​

​java.util​

​ 包下面的一些集合類(List/Set/Map等),這類集合指向的資料是存儲在堆上,意味着資料的數量不必在編譯期就已知,并且還能随着程式的運作增大或縮小,每種集合都有其适用的場景,在我們日常開發過程中是非常有用的。

1、Vector

1.1 作用

由标準庫提供,用來存儲多個相同類型的值,其值在記憶體中是連續存放的。

相關 api 介紹:​​https://doc.rust-lang.org/std/vec/struct.Vec.html​​

1.2 建立

①、Vec::new 函數

fn main() {
    let v: Vec<i32> = Vec::new();
}      

因為沒有向這個 vector 中插入任何值,Rust 并不知道我們想要儲存什麼類型的元素,是以無法進行類型推斷,這裡我們就增加了泛型​

​<i32>​

​​ ,表示這個集合 v 隻能存放 ​

​i32​

​ 類型的資料。

②、vec![] 宏

fn main() {
    let v = vec![1, 2, 3];
}      

這裡我們提供了 ​

​i32​

​​ 類型的初始值,Rust 可以推斷出 ​

​v​

​​ 的類型是 ​

​Vec<i32>​

​,是以不需要加上泛型注解。

1.3 添加
fn main() {
    let mut v: Vec<i32> = Vec::new();
    v.push(1);
    v.push(2);
}      

通過 push() 向集合末尾添加元素,注意要聲明為 ​

​mut​

​ 使其可變。

1.4 修改

直接通過下标的方式修改:

fn main() {
    let mut v: Vec<i32> = Vec::new();
    v.push(1);
    v.push(2);
    v[0] = 3;
}      
1.5 删除

①、通過下标删除

fn main() {
    let mut v: Vec<i32> = Vec::new();
    v.push(1);
    v.push(2);
    v.remove(0);
}      

②、删除末尾元素

v.pop();      
1.6 周遊
fn main() {
    let mut v: Vec<i32> = vec![1,2,3,4];
    // 周遊引用位址
    for x in &v{
        print!("{} ", x);
    }

    // 周遊下标
    for x in 0..v.len(){
        if let Some(num) = v.get(x) {
            print!("{} ", num);
        }
    }

    for x in v.iter() {
        print!("{} ", x);
    }

    for x in v.into_iter() {
        print!("{} ", x);
    }
}      
1.7 周遊修改
fn main() {
    let mut v: Vec<i32> = vec![1,2,3,4];
    for x in &mut v {
        *x += 1;
    }
    println!("&mut v {:?}", v);
    for x in v.iter_mut() {
        *x += 1;
    }
    println!("v.iter_mut {:?}", v);
    for x in 0..v.len() {
        if let Some(num) = v.get_mut(x) {
            *num += 1;
        }
    }
    println!("0..v.len() get_mut {:?}", v);
    let v1: Vec<i32> = v.iter().map(|x| x + 1).collect();
    println!("v.iter().map().collect() {:?}", v1);

}      
1.8 使用枚舉存儲不同類型

前面我們說vector 隻能儲存相同類型的值,但實際會有很多情況下我們要存儲不同類型的值,這時候就可以使用枚舉。

因為枚舉成員都被定義為相同的枚舉類型。

fn main() {
    let row = vec![
        SpreadsheetCell::Int(3),
        SpreadsheetCell::Text(String::from("blue")),
        SpreadsheetCell::Float(10.12),
    ];
}

enum SpreadsheetCell {
    Int(i32),
    Float(f64),
    Text(String),
}      

2、HashMap

2.1 作用

基于 hash 算法的存儲一組鍵值對 (key- value- pair) 的容器,可以通過 K(任意類型)來尋找資料,而不是通過索引。

2.2 建立

注意必須首先通過 ​

​use​

​​ 引用标準庫中集合部分的 ​

​HashMap​

​​。​

​HashMap​

​ 沒有被 prelude 自動引用。

标準庫中對 ​

​HashMap​

​ 的支援也相對較少,例如,并沒有内建的建構宏。

use std::collections::HashMap;
let mut map = HashMap::new();      

PS:注意上面不指明 map 的類型,編譯是會報錯的。要麼指明編譯類型 ​

​let mut map: HashMap<String,i32> = HashMap::new()​

​ ;要麼通過類型推斷,像 map 中添加資料。

2.3 添加
fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);
}      

像 vector 一樣,哈希 map 将它們的資料儲存在堆上,這個 ​

​HashMap​

​​ 的鍵類型是 ​

​String​

​​ 而值類型是 ​

​i32​

​。

類似于 vector,哈希 map 是同質的:所有的鍵必須是相同類型,值也必須都是相同類型。

2.4 修改

①、覆寫一個值

用相同的鍵插入一個不同的值,也就是連續調用兩次 insert ,其 key 相同,value 不同。

fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Blue"), 50);
    println!("{:?}", scores);//{"Blue": 50}
}      

②、key 不存在則插入,存在就不做操作

fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.entry(String::from("Yellow")).or_insert(50);
    scores.entry(String::from("Blue")).or_insert(50);
    println!("{:?}", scores);//{"Blue": 10, "Yellow": 50}
}      

​Entry​

​​ 的 ​

​or_insert​

​ 方法在鍵對應的值存在時就傳回這個值的可變引用,如果不存在則将參數作為新值插入并傳回新值的可變引用。

③、key 不存在則插入,存在做更新操作

fn main() {
    use std::collections::HashMap;
    let text = "hello world wonderful world";
    let mut map = HashMap::new();
    for word in text.split_whitespace() {
        let count = map.entry(word).or_insert(0);
        *count += 1;
    }

    println!("{:?}", map);
}      

列印結果:

{"world": 2, "hello": 1, "wonderful": 1}

由于​

​Entry​

​​ 的 ​

​or_insert​

​​ 方法在鍵對應的值存在時會傳回這個值的可變引用,我們通過 ​

​*​

​ 解引用然後去修改裡面的值。

2.5 删除
fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"),50);
    scores.remove(&String::from("Yellow"));
    println!("{:?}", scores);//{"Blue": 10}
}      
2.6 周遊
fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"),50);
    println!("{:?}", scores);//{"Blue": 10}
    for (key, value) in &scores {
        println!("{}: {}", key, value);
    }
}