【跟小嘉学 Rust 编程】八、常见的集合

系列文章目录

【跟小嘉学 Rust 编程】一、Rust 编程基础
【跟小嘉学 Rust 编程】二、Rust 包管理工具使用
【跟小嘉学 Rust 编程】三、Rust 的基本程序概念
【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念
【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据
【跟小嘉学 Rust 编程】六、枚举和模式匹配
【跟小嘉学 Rust 编程】七、使用包(Packages)、单元包(Crates)和模块(Module)来管理项目
【跟小嘉学 Rust 编程】八、常见的集合

前言

Rust 的标准库包括许多非常有用的数据结构,称为集合。大多数其他数据类型表示一个特定的值,但是集合可以包含多个值。与内置数组和元组类型不同,这些集合指向的数据存储在堆中。

本章节主要讲解 Vector、String、HashMap

主要教材参考 《The Rust Programming Language》


一、Vector

1.1、Vector 是什么

Vector 由标准库提供,可以存储多个相同类型的数据,其值在内存中连续存放。

1.2、创建一个 Vector 变量

1.2.1、使用 Vec:: new 创建 Vector 类型变量

使用 Vec:: new 可以创建一个空的 Vector

	let v: Vec<i32> = Vec::new();

1.2.2、使用 vec!宏 创建 Vector 类型变量

    let v = vec![1, 2, 3];

1.2.3、使用 with_capacity 创建 Vector 类型变量

//定义一个容量为6的空向量,这时向量的长度为0
let mut vec: Vec<i32> = Vec::with_capacity(6);
//添加第一个元素,此时长度为1
vec.push(1);
//添加第二个元素,长度加1
vec.push(2);

1.3、更新 Vector

1.3.1、使用 push 方法添加元素

    let mut v = Vec::new();
    v.push(5);
    v.push(6);
    v.push(7);
    v.push(8);

1.3.2、使用 insert(index: usize, element: T) 方法

fn main() {
    
    
    let mut v = Vec::new();
    v.insert(0, 3);
}   

index 从0 开始

1.3.3、使用 pop 方法

使用 pop 方法可以弹出最后一个值。

1.3.4、使用 remove 方法

按照索引方式删除。

1.3.5、使用 retain 方法

只保留符合条件的元素。

let mut vec = vec![1, 2, 3, 4];
vec.retain(|&x| x % 2 == 0);

1.3.6、使用 clear 方法

删除所有的值。

1.4、读取 Vector 中的元素

1.4.1、使用索引方式

    let v = vec![1, 2, 3, 4, 5];
    let third: &i32 = &v[2];
    println!("The third element is {third}");

使用 索引方式 获取值操过索引范围程序则会抛出 panic。

1.4.2、使用get()方法

    let v = vec![1, 2, 3, 4, 5];
    let third: Option<&i32> = v.get(2);
    match third {
    
    
        Some(third) => println!("The third element is {third}"),
        None => println!("There is no third element."),
    }

1.5、遍历 Vector

1.5.1、遍历读取

    let v = vec![100, 32, 57];
    for i in &v {
    
    
        println!("{i}");
    }

1.5.2、遍历修改

    let mut v = vec![100, 32, 57];
    for i in &mut v {
    
    
        *i += 50;
    }

1.5.3、判断是否为空vector

let mut v = vec![1, 2, 3];
v.clear();
assert!(v.is_empty());

1.5.6、判断是否有指定元素

let vector : Vec<i32> = vec![2,11,10];
vector.contains(&200); // false
vector.contains(&2); // true

1.5.7、排序和二分查找

	let mut vector = vec![10,22,3,14,51,16,27];
    vector.sort(); // 排序
    vector.binary_search(&22);  // 二分查找

1.6、Vector 和 Enum

使用枚举可以让 Vector 存放不同类型的数据。

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

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

二、String

2.1、字符串切片和String 类型转换

fn main() {
    
    
    let str1:String =  "hello".to_string();
    let str2:String =  String::from("hello");
    let str2:String =  "hello".to_owned();
}

2.2、更新字符串

    let mut str1:String =  "hello".to_string();
    let str2:String =  String::from("hello");
    let str2:String =  "hello".to_owned();

    str1.insert(1, 'c');
    str1.insert_str(1, "str");
  • push_str 的时候 push的是字符串切片,调用了之后原字符串还可以使用的;
  • push 字符;

2.3、遍历字符串

for c in "Зд".chars() {
    
    
    println!("{c}");
}

for b in "Зд".bytes() {
    
    
    println!("{b}");
}

三、HashMap<K, V>

3.1、HashMap<K, V>类型

HashMap<K, V> 使用散列函数存储 K类型键到 V类型值的映射,该函数决定如何将这些键和值放入内存。

3.2、创建一个新的 HashMap 对象

3.2.1、使用 new 方法来创建HashMap对象

use std::collections::HashMap;
let mut scores:HashMap<String, i32> = HashMap::new();

如果创建空对象,不插入内容,编译器无法进行类型自动推导,所以需要显示指定类型。

3.2.2、使用 collect 方法来创建HashMap对象

use std::{
    
    vec, collections::HashMap};

fn main() {
    
    
    let teams = vec![String::from("Blue"), String::from("Yellow")];
    let intial_score = vec![10,50];

    let scores:HashMap<_,_> = teams.iter().zip(intial_score.iter()).collect();
    println!("{:?}", scores);
}

3.2.3、使用 with_capacity 方法来创建 HashMap

let mut scores:HashMap<String, i32> = HashMap::with_capacity(16);

3.3、使用 insert 方法插入数据

use std::collections::HashMap;

fn main() {
    
    
    let mut scores:HashMap<String, i32> = HashMap::with_capacity(16);
    let key= String::from("value");
    let value = 32;
    scores.insert(key, value);
}

需要注意 HashMap和所有权的问题

  • 对于实现了 Copy trait的类型,值会被复制到 HashMap;
  • 对于拥有所有权的值(例如String),值回被移动,所有权会转移给 HashMap;
  • 如果将值的引用插入到 HashMap,值本身不会移动
    • 在HashMap有效的期间,被引用的值必须保持有效

3.4、访问 HashMap 中的值

3.4.1、使用 get 方法访问

get 方法返回的是 Option 枚举。

use std::collections::HashMap;

fn main() {
    
    
    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);

    let team_name = String::from("Blue");
    let score = scores.get(&team_name);

    match score {
    
    
        Some(s) => println!("{:?}",s),
        None => println!("{} not exits", team_name),
    }

}

3.4.2、使用 get 方法访问获取不到给返回值

这其实是 Optional 的使用方法

use std::collections::HashMap;

fn main() {
    
    
    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);

    let team_name = String::from("Blue");
    let score = scores.get(&team_name).copied().unwrap_or(0);

}

3.4.2、for 循环遍历 HashMap

use std::collections::HashMap;

fn main() {
    
    
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);
    
    for (key, value) in &scores {
    
    
        println!("{key}: {value}");
    }
}

3.5、覆盖指定 key的value

use std::collections::HashMap;

fn main() {
    
    
    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Blue"), 25);

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

3.6、如果key不存在添加值

3.6.1、如果key不存在添加值

use std::collections::HashMap;

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);
}

3.6.2、例子:单词个数统计

use std::collections::HashMap;

fn main() {
    
    
    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);
}

3.7、Hash 函数

默认情况下,HashMap 使用加密功能强大的 Hash 函数(SipHash),可以抵抗拒绝服务(DoS)攻击。该方法不是可用的最快的 Hash 算法,但是具有更好的安全性。

可以指定不同的 hasher(实现 BuildHasher trait) 来切换到另个函数。

总结

以上就是今天要讲的内容

  • 讲解了 Vector 类型的基本用法,使用场景,以及涉及到的所有权;
  • 讲解 String 类型的部分用法;
  • 讲解了 HashMap 类型的基本使用方法;

猜你喜欢

转载自blog.csdn.net/fj_Author/article/details/131416652