本文介绍了 Rust 中的数组(静态数组和动态数组)和 HashMap 的基本概念、创建方法、操作及其内部机制,包括数组的固定长度与动态扩展、HashMap 的键值对存储与扩容策略。
数组是由多个相同类型的元素组合而成的集合。在 Rust 中,数组主要分为两类:
静态数组的特点类似于一个固定大小的书架,一旦确定其大小,就无法再改变。相比之下,动态数组更像是一个可以随时调整大小的抽屉,可以根据需要扩展或缩小。
// 由编译器推断类型
let a = [10, 20, 30, 40, 50];
// 显式指定类型和长度
let b: [i32; 5] = [10, 20, 30, 40, 50];
// 创建包含相同元素的数组
let c = [7; 5];  // c = [7, 7, 7, 7, 7]fn main() {
    // 静态数组:长度固定,存储在栈上
    let a = [5u8; 5]; // a = [5, 5, 5, 5, 5]
    // 非基础类型的数组需要使用 `std::array::from_fn` 来初始化
    let b: [String; 3] = std::array::from_fn(|_| "hello".to_string()); 
    // b = ["hello", "hello", "hello"]
    // 数组的元素访问
    let c: [u8; 5] = [15, 25, 35, 45, 55];
    let first = c[0];  // first = 15
    let second = c[1]; // second = 25
    // 访问数组越界元素(会导致编译错误)
    // let none_element = c[100];
    // 二维数组:每个元素都是一个 `[u8; 5]` 类型的数组
    let arrays: [[u8; 5]; 2] = [a, c]; 
}动态数组 Vec<T> 是 Rust 中可变长度的集合,允许在运行时动态调整大小。与 String 不同,Vec<T> 是通用的,可存储任意类型的元素。
// 显式声明类型
let v1: Vec<i32> = Vec::new();
// 让编译器推断类型。
let mut v2 = Vec::new();
v2.push(10);
// 使用 vec! 宏创建并初始化
let v3 = vec![10, 20, 30];
// 使用 [初始值;长度] 来创建数组
let v4 = vec![1; 3];  // v4 = [1, 1, 1]
// 使用from语法创建数组
let v5 = Vec::from([1, 1, 1]);fn main() {
    let mut v = vec![1, 2, 3, 4, 5];
    // 访问元素
    let first: &i32 = &v[0];
    println!("第一个元素是 {}", first);
    // 通过 get 方法安全访问
    if let Some(last) = v.get(4) {
        println!("最后一个元素是 {}", last);
    }
    // 修改元素
    for i in &mut v {
        *i *= 2;
    }
    println!("修改后的 v: {:?}", v); // [2, 4, 6, 8, 10]
    // 删除元素
    v.pop();
    println!("删除最后一个元素后: {:?}", v); // [2, 4, 6, 8]
    v.remove(1);
    println!("删除索引 1 处的元素后: {:?}", v); // [2, 6, 8]
}fn main() {
    let mut v = vec![1, 2, 3, 4];
    println!("初始容量: {}", v.capacity());
    println!("初始 v[0] 的地址: {:p}", &v[0]);
    v.push(5);
    println!("添加一个元素后,容量: {}", v.capacity());
    println!("添加后 v[0] 的地址: {:p}", &v[0]);
    v.push(6);
    println!("再次添加元素后,容量: {}", v.capacity());
    println!("再次添加后 v[0] 的地址: {:p}", &v[0]);
}初始时 Vec 的容量可能是 4,存储在堆内存中,而栈上存储着指向堆的指针。当 push(5) 触发扩容时,Vec 会申请更大的空间(通常是当前容量的 2 倍),并将数据复制到新的地址。
HashMap 是键值对(key-value)存储结构,可以通过键快速检索值。Rust 使用散列函数计算键的位置,从而提高查找效率。
// 由于 HashMap 并没有包含在 Rust 的 prelude 库中,所以需要手动引入
use std::collections::HashMap;
fn main() {
    // 创建一个HashMap,用于存储学生姓名和他们的年龄
    let mut student_ages = HashMap::new();
    student_ages.insert("Alice", 20);
    student_ages.insert("Bob", 19);
    student_ages.insert("Charlie", 21);
    // 创建一个指定容量的 HashMap,用于存储学生姓名和他们的身高
    // 这样可以预先分配内存,减少后续插入时的内存分配开销
    let mut student_heights = HashMap::with_capacity(4);
    student_heights.insert("Alice", 165);
    student_heights.insert("Bob", 180);
    student_heights.insert("Charlie", 175);
    student_heights.insert("David", 170);
    // 打印 HashMap 的内容
    println!("学生年龄: {:?}", student_ages);
    println!("学生身高: {:?}", student_heights);
}
use std::collections::HashMap;
fn main() {
    // 创建一个包含用户姓名和积分的列表
    let user_list = vec![
        ("Alice", 300),
        ("Bob", 250),
        ("Eve", 150),
        ("Mallory", 50),
    ];
    // 将列表转换为 HashMap
    let mut user_map: HashMap<&str, i32> = user_list.into_iter().collect();
    println!("用户积分: {:?}", user_map);
    // 获取元素
    let alice_points = user_map["Alice"];
    println!("Alice 的积分: {}", alice_points);
    // 使用 get 方法安全获取元素
    let alice_points = user_map.get("Alice");
    println!("Alice 的积分: {:?}", alice_points);
    // 尝试获取不存在的键
    let trent_points = user_map.get("Trent");
    println!("Trent 的积分: {:?}", trent_points);
    // 覆盖已有的值,insert 会返回旧值
    let old = user_map.insert("Alice", 400); // 更新 Alice 的积分
    assert_eq!(old, Some(300)); // 确认旧值是 300
    // 使用 entry 方法插入或获取值
    let v = user_map.entry("Trent").or_insert(100); // Trent 不存在,插入 100
    assert_eq!(*v, 100);
    let v = user_map.entry("Trent").or_insert(200); // Trent 已存在,不会修改
    assert_eq!(*v, 100);
    // 打印更新后的 HashMap
    println!("更新后的用户积分: {:?}", user_map);
}HashMap 提供 entry().or_insert() 方法,允许在键不存在时插入默认值,而不会覆盖已有值。例如,Trent 不存在时,or_insert(100) 会插入 100,但后续 or_insert(200) 不会修改已存在的值。
 
                如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!