常见集合(8)

常见集合

1.使用Vector存储列表

  • vector允许我们一个挨着一个地存储一系列数量可变的值

1.1新建vector

1.新建一个空的vector来存储i32类型的值
rust 复制代码
let v: Vec<i32> = Vec::new();
2.新建一个包含初值的vector
  • 为了方便Rust提供了Vec!宏,这个宏会根据提供的值来创建一个新的Vector
rust 复制代码
// 默认推断为i32的数据类型,i32是默认整数类型
let v = vec![1,2,3];

1.2更新vector

  • 向vector增加元素,使用push方法
rust 复制代码
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);

1.3读取vector的元素

  • 读取vector中存储的值有两种方式
    • 索引
    • get方法
rust 复制代码
fn main() {
    let v = vec![1, 2, 3, 4, 5, 6];
    let third: &i32 = &v[2];
    println!("The third element is {third}");

    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.使用索引语法或get方法来访问vector中的项
  • 索引语法
    • 索引是从数字0开始的,使用**&**和[ ]会得到一个索引位置元素的引用
    • 越界索引 ,引用一个不存在的元素时Rust会造成panic
  • get方法
    • 使用索引作为参数调用get 方法时,会得到一个可以用于match的Option<&T>
    • 越界索引 ,不会panic ,而是返回None
2.在拥有vector中项的引用的同时向其增加一个元素
  • 注意事项
rust 复制代码
fn main() {
    let mut v = vec![1, 2, 3, 4, 5, 6];
    //引用
    let first = &v[0];
    //在vector的结尾增加新元素时,在没有足够空间将所有元素依次相邻存放的情况下,可能会要求分配新内存并将老的元素拷贝到新的空间中
    v.push(6);
    // 第一个元素的引用就指向了被释放的内存,运行报错
    println!("The first element is: {first}");
}

1.4遍历vector中的元素

1.通过for循环遍历vector的元素
rust 复制代码
let v = vec![110,23,96];
for i in &v{
	println!("{i}")
}
2.遍历vector中元素的可变引用
rust 复制代码
let mut v = vec![300,23,54];
for i in &mut v{
	*i += 50;
}

1.5使用枚举来存储多种类型

rust 复制代码
enum SpreadsheetCell{
	Int(i32),
	Float(f64),
	Text(String),
}
let row = vec![
	SpreadsheetCell::Int(3),
	SpreadsheetCell::Text(String::from("blue")),
	SpreadsheetCell::Float(10.12),
];

1.6丢弃vectorr时也会丢弃其所有元素

  • 类似于任何其他的struct,vector在其离开作用域时会被释放
rust 复制代码
{
	let v = vec![1,2,3,4];
	// do stuff with v
}
//v goes out of scope and is freed here

1.7移除vector的元素

rust 复制代码
fn main() {
    let mut v = vec![1, 2, 3, 4, 5, 6];
    let num: Option<i32> = v.pop();
    match num {
        Some(num) => println!("{num}"),
        None => println!("There is no number"),
    }
    for i in &v {
        print!("{i} "); // 1 2 3 4 5
    }
}

2.使用字符串存储UTF-8编码的文本

  • 字符串是字符的集合

2.1什么是字符串

  • Rust的核心语言中只有一种字符串类型: 字符串 slice str ,通常以被借用的形式出现 &str
  • 字符串(String )类型由Rust标准库提供,而不是编入核心语言 ,它是一种可增长可变可拥有UTF-8编码的字符串类型
  • Rustaceans提及Rust中的"字符串"时,可能指的是Stringstring slice &str类型,而不是其中仅仅一种类型

2.2新建字符串

1.新建一个空的String
rust 复制代码
let mut s = String::new();
2.使用to_string方法从字符串字面值创建String
rust 复制代码
fn main() {
    let data = "initial contents";
    let s = data.to_string();
    println!("{s}");
    //该方法也可直接用于字符串字面值
    let s = "initial contents".to_string();
}
3.使用String::from函数从字符串字面值创建String
  • String::from.to_string最终做了完全相同的工作
rust 复制代码
let s = String::from("initial contents");

2.3更新字符串

  • String的大小可以增加,其内容也可以改变
  • 可以使用 + 运算符或 format! 宏来拼接String值
1.使用 push_str 和 push 附加字符串
  • 可以通过 push_str 方法来附加字符串slice,从而使 String 变长
rust 复制代码
fn main() {
    let mut str = String::from("foo");
    let new_str = "bar";
    str.push_str(new_str);
    println!("new_str is {new_str}"); // new_str is bar
}
  • 使用push将一个字符加入String值中
rust 复制代码
fn main() {
    let mut s = String::from("lo");
    s.push('l');
    println!("{s}"); //lol
}

2.4使用 +运算符或 format!宏拼接字符串

1.使用运算符 + 将两个String值合并到一个新的String值中
rust 复制代码
fn main() {
    let s1 = String::from("Hello, ");
    let s2 = String::from("world");
    let s3 = s1 + &s2;
    println!("{s3}");
    // 注意S1被移动了,不能继续使用
    //println!("{s1}");
}
2.使用 format! 宏
rust 复制代码
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");

//对于复杂的字符串连接,使用format!宏,更加直观
let s = s1 + "-"+ &s2 + "-" + &s3;

let new_s = format!("{s1}-{s2}-{s3}");

2.5索引字符串

  • Rust的字符串不支持索引
  • String是一个Vec< u8>的封装

2.6字符串slice

rust 复制代码
let hello = "Здравствуйте";
let s = &hello[0..4];// Зд

2.7遍历字符串的方法

1.字符
rust 复制代码
for c in "Зд".chars(){
	println!("{c}");// З  д
}
2.字节
rust 复制代码
for b in "Зд".bytes(){
	println!("{b}");//  208  151  208 180

}

3.使用Hash Map存储键值对

  • 允许我们将值与一个特定的键(key)相关联
  • 所有的键必须是相同类型,值必须都是相同类型

3.1新建一个哈希map

rust 复制代码
use std::collections::HashMap;

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

3.2访问哈希map中的值

1.访问哈希map的值
rust 复制代码
use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);
}
2.访问哈希map的键值对
rust 复制代码
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);
    println!("{score}"); // 10

    for (key, value) in &scores {
        println!("{key}: {value}");
    }
}

3.哈希map和所有权

  • i32实现了Copy trait的类型,其值可以拷贝进哈希map
  • String这种拥有所有权的值,其值将被移动到哈希map会称为这些值的所有者
rust 复制代码
use std::collections::HashMap;
fn main() {
    let field_name = String::from("Favorite color");
    let field_value = String::from("Blue");

    let mut map = HashMap::new();
    map.insert(field_name, field_value);
    // field_name和field_value 移动到哈希map中,将不能使用这个两个绑定
    //println!("The is key:{field_name}");
}

4.更新哈希map

1.覆盖一个值
rust 复制代码
use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert(String::from("Blue"),10);
scores.insert(String::from("Blue"),25);

println!("{:?}",scores);// {"Blue": 25}
2.只在键没有对应值时插入键值对
  • Entryor_insert 方法在键对应的值存在时就返回这个值的可变引用,如果不存在则将参数作为新值插入并返回新值的可变引用
rust 复制代码
use std::collections::HashMap;
fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 5);

    
    scores.entry(String::from("Yellow")).or_insert(50);
    scores.entry(String::from("Blue")).or_insert(50);

    println!("{:?}", scores);// {"Yellow": 50, "Blue": 5}
}
3.根据旧值更新一个值
rust 复制代码
use std::collections::HashMap;
fn main() {
    let text = "hello world wonderful world";
    let mut map = HashMap::new();
    for word in text.split_whitespace() {
        // or_insert方法返回这个键的值的一个可变引用(&mut v)
        let count = map.entry(word).or_insert(0);
        *count += 1;
    }
    println!("{:?}", map); // {"world": 2, "wonderful": 1, "hello": 1}
}
相关推荐
海绵波波1072 小时前
flask后端开发(10):问答平台项目结构搭建
后端·python·flask
网络风云3 小时前
【魅力golang】之-反射
开发语言·后端·golang
Q_19284999063 小时前
基于Spring Boot的电影售票系统
java·spring boot·后端
运维&陈同学5 小时前
【Kibana01】企业级日志分析系统ELK之Kibana的安装与介绍
运维·后端·elk·elasticsearch·云原生·自动化·kibana·日志收集
Javatutouhouduan7 小时前
如何系统全面地自学Java语言?
java·后端·程序员·编程·架构师·自学·java八股文
后端转全栈_小伵7 小时前
MySQL外键类型与应用场景总结:优缺点一目了然
数据库·后端·sql·mysql·学习方法
编码浪子8 小时前
Springboot高并发乐观锁
后端·restful
uccs8 小时前
go 第三方库源码解读---go-errorlint
后端·go
Mr.朱鹏9 小时前
操作002:HelloWorld
java·后端·spring·rabbitmq·maven·intellij-idea·java-rabbitmq
编程洪同学10 小时前
Spring Boot 中实现自定义注解记录接口日志功能
android·java·spring boot·后端