Rust学习记录--C8 常用的集合

C8 常用的集合

与数组和tuple不同,下面的集合都存放在heap上

  • 存放在heap上
  • 无需在编译时确认集合的大小
  • 在运行时动态的变大或者变小

Vector

特性

  • 形式: Vec<T>
  • 由标准库提供
  • 可以存储多个值
  • 只存储相同类型的数据
  • 值在内存中连续存放

创建Vector

创建一个空的vector

  • Vec::new函数

    rust 复制代码
    fn main(){
    		// 空的vector编译器无法推断类型,所以需要显式指定具体类型Vec<i32>
    		// 但是下面有一些奇怪的特例
        let v: Vec<i32> = Vec::new();
    }

指定初始值的方式创建Vector

  • 通常使用指定初始值的方式创建Vector:使用vec!

    rust 复制代码
    fn main(){
        let v = vec![1,2,3];
    }

更新Vector

添加元素

  • 向Vector添加元素,使用push方法
rust 复制代码
fn main(){
    let mut v = Vec::new();
    v.push(2);
}

删除Vector

  • 与其他struct一样,离开作用域就会被清理,里面元素也被清理

读取Vector的元素

  • 有两种方式可以引用Vector里的值
    • 索引: &v[index]

    • get 方法: v.get(index)
      注意:get方法的返回值类型是Option<T>

    • 两者的区别

      索引 get 方法
      调用方式 &v[index] v.get(index)
      返回值类型 和本身vec内部的值一致 Option<T>
      访问超出范围的索引(访问越界) 引发panicked 返回None
rust 复制代码
fn main(){
    let mut v = vec![0,1,2,3];
    let aa = &v[2];
    println!("aa: {}", aa);

    match v.get(10) {
   		// 能取到这个值
        Some(i) => {
            println!("The value is {}", i)
        },
        // 取不到这个值,比如说index大于3
        None => println!("None"),
    }
}

所有权和借用规则

  • 不能在统一作用域内同时用于可变和不可变引用
  • 具体看下面的例子

遍历Vector中的值

  • for 循环
rust 复制代码
fn main(){
    let v = vec![0,1,2,3];
    for i in &v {
        println!("{}", i);
    }
}

对于可变的vector

rust 复制代码
fn main(){
    let mut v = vec![0,1,2,3];
    for i in &mut v {
    		// TODO *i解引用
        println!("{}", *i+50);
    }
}

使用enum来存储多种数据类型并且存在Vector中

可附加数据的enum变体

rust 复制代码
// 创建一个ExcelCell枚举类型,里面可以存储i32的Int。。。
enum ExcelCell{
    Int(i32),
    Text(String),
    Float(f64),
}

fn main()
{
    let vv = vec![
        ExcelCell::Int(12),
        ExcelCell::Float(6.33),
        ExcelCell::Text("xiaoming".to_string())
    ];
}

String

String的难点

  • Rust倾向于暴露可能的错误
  • 字符串数据结构复杂
  • rust使用UTF-8编码(TODO)

字符串是什么

  • 字符串是Byte的集合
  • 提供了一些方法可以将byte解析为文本

通常说的字符串是指String和&str,标准库中也有其他的字符串类型:OsString/OsStr/CString/CStr

  • 在rust的核心语言层面,只有一个字符串类型:字符串切片str(或&str)
    • 字符串切片:对存储在其他地方/UTF-8编码的字符串的引用
    • 字符串字面值:存储在二进制文件中->也是字符串切片
  • String类型
    • 来自标准库
    • 可增长/修改/可获得所有权
    • UTF-8编码

创建String

Vector的很多操作都可以用于String

  • 创建空的string:String::new()函数
  • 创建包含初始值的String
    • to_string()方法,可用于实现了Display trait,包括字符串字面值
    • String::from()函数,从字面值创建String

更新String

  • push_str()方法,把一个字符串切片附加到String
rust 复制代码
fn main()
{
    let aa = "Hello";
    let mut y = aa.to_string();
    // push_str内部参数类型是&str
    y.push_str(", world");
    println!("{}",y);
}
  • push()方法,把单个字符附加到String
rust 复制代码
fn main()
{
    let aa = "Hell";
    let mut y = aa.to_string();
    y.push('o');
    println!("{}",y);
}
  • +,拼接字符串
    • 要求 +前面是String类型,后面是&str
rust 复制代码
fn main()
{
    let str1 = String::from("Hello");
    let str2 = String::from(" World");
    let st = str1 + &str2;
    println!("{}",st);
}

在执行完let st = str1 + &str2;后str1的所有权失效,但是str2的所有权仍然保留

  • format!,连接多个字符串(类似println!)
    • format!的优点:更简单,且不会获得参数的所有权
rust 复制代码
let str1 = String::from("He");
    let str2 = String::from("ll");
    let str3 = String::from("o");
    let s = str1 + "-" + &str2  + "-" + &str3;

等效于

rust 复制代码
    // let s = str1 + "-" + &str2  + "-" + &str3;
    let s = format!("{}-{}-{}",str1,str2,str3);

String的内部表示

  • 不支持索引访问
  • 内部表示
    • String是对Vec<u8>的包装
    • len() 方法
      // str1.len()的返回值是2。但是对于有一些字符,它一个字符所占的字节数就不是1,所以s.len()就不一定是字符的个数。
      // 所以导致了rust避免使用索引去访问String
rust 复制代码
let str1 = String::from("He");
println!("{}",str1.len());
  • Rust中三种看待字符串的方式:
    • 字节:s.bytes()
    • 标量值: s.chars()
    • 字形簇(最接近所谓的'字母')

切割String

  • 可以使用[]一个范围来创建字符串的切片
    • &str1[0...2] 需要谨慎使用,如果切割跨越了字符的边界就会panic
rust 复制代码
let str1 = String::from("He1110");
let s = &str1[0..2]

遍历String

  • 字节:s.bytes()
  • 标量值: s.chars()

HashMap

2026/1/8

相关推荐
C_心欲无痕16 小时前
js - AbortController请求中止
开发语言·javascript·ecmascript
yugi98783816 小时前
基于Matlab的晴空指数计算实现
开发语言·算法·matlab
song1502653729816 小时前
空间站太阳能帆板电池 组件性能测试 AM0太阳光模拟器
开发语言·python
不会c嘎嘎16 小时前
QT中的常用控件 (三)
开发语言·qt
代码方舟16 小时前
Java企业级风控实战:对接天远多头借贷行业风险版API构建信贷评分引擎
java·开发语言
闫有尽意无琼16 小时前
Qt局部变量“遮蔽(shadow)”成员变量导致lambda传参报错
开发语言·qt
星火开发设计16 小时前
Python数列表完全指南:从基础到实战
开发语言·python·学习·list·编程·知识·期末考试
工程师00716 小时前
C# 动态编程(基于 dynamic 类型)
开发语言·c#·dynamic·动态编程
南桥几晴秋16 小时前
Qt显示类控件
开发语言·c++·qt