rust hashmap 全面使用指南

我來詳細(xì)介紹 Rust 中 HashMap 的使用方法。

HashMap 基礎(chǔ)用法

1. 引入和創(chuàng)建

use std::collections::HashMap;

fn main() {
    // 方法1: 創(chuàng)建空的 HashMap
    let mut map: HashMap<String, i32> = HashMap::new();
    
    // 方法2: 使用 with_capacity 預(yù)分配容量
    let mut map2: HashMap<String, i32> = HashMap::with_capacity(10);
    
    // 方法3: 從迭代器創(chuàng)建
    let map3: HashMap<&str, i32> = [("a", 1), ("b", 2), ("c", 3)]
        .iter()
        .cloned()
        .collect();
    
    // 方法4: 使用 HashMap::from (Rust 1.56+)
    let map4 = HashMap::from([
        ("apple", 3),
        ("banana", 2),
        ("orange", 5),
    ]);
}

2. 插入和訪問

use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();
    
    // 插入鍵值對(duì)
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);
    
    // 訪問值
    let team_name = String::from("Blue");
    
    // 方法1: get() 返回 Option<&V>
    match scores.get(&team_name) {
        Some(score) => println!("Blue team score: {}", score),
        None => println!("Team not found"),
    }
    
    // 方法2: 使用 unwrap_or 提供默認(rèn)值
    let score = scores.get(&team_name).unwrap_or(&0);
    println!("Score: {}", score);
    
    // 方法3: 使用索引訪問 (會(huì) panic 如果鍵不存在)
    // let score = &scores[&team_name]; // 謹(jǐn)慎使用
}

3. 更新值的不同方式

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    
    // 1. 直接覆蓋
    map.insert("key1", 10);
    map.insert("key1", 20); // 覆蓋之前的值
    
    // 2. 只在鍵不存在時(shí)插入
    map.entry("key2").or_insert(30);
    map.entry("key2").or_insert(40); // 不會(huì)覆蓋,key2 仍然是 30
    
    // 3. 基于現(xiàn)有值更新
    let count = map.entry("key3").or_insert(0);
    *count += 1; // 增加計(jì)數(shù)
    
    // 4. 復(fù)雜的更新邏輯
    map.entry("key4")
        .and_modify(|v| *v += 10)  // 如果存在,加10
        .or_insert(5);             // 如果不存在,插入5
        
    println!("{:?}", map);
}

4. 遍歷 HashMap

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::from([
        ("apple", 3),
        ("banana", 2),
        ("orange", 5),
    ]);
    
    // 1. 遍歷鍵值對(duì)
    for (key, value) in &map {
        println!("{}: {}", key, value);
    }
    
    // 2. 只遍歷鍵
    for key in map.keys() {
        println!("Key: {}", key);
    }
    
    // 3. 只遍歷值
    for value in map.values() {
        println!("Value: {}", value);
    }
    
    // 4. 可變遍歷值
    for value in map.values_mut() {
        *value += 1; // 所有值加1
    }
    
    // 5. 遍歷并獲取所有權(quán)
    for (key, value) in map {
        println!("Owned: {} = {}", key, value);
    }
    // 注意:map 在這里被移動(dòng)了,后面不能再使用
}

5. 常用方法

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert("a", 1);
    map.insert("b", 2);
    map.insert("c", 3);
    
    // 檢查是否包含鍵
    if map.contains_key("a") {
        println!("包含鍵 'a'");
    }
    
    // 獲取長度
    println!("HashMap 長度: {}", map.len());
    
    // 檢查是否為空
    if !map.is_empty() {
        println!("HashMap 不為空");
    }
    
    // 移除鍵值對(duì)
    if let Some(value) = map.remove("b") {
        println!("移除了 'b': {}", value);
    }
    
    // 清空 HashMap
    map.clear();
    println!("清空后長度: {}", map.len());
    
    // 容量相關(guān)
    map.reserve(100); // 預(yù)留容量
    println!("容量: {}", map.capacity());
    
    map.shrink_to_fit(); // 縮減到合適大小
}

6. 處理復(fù)雜數(shù)據(jù)類型

use std::collections::HashMap;

#[derive(Debug)]
struct Student {
    name: String,
    age: u32,
    grade: f64,
}

fn main() {
    // HashMap 存儲(chǔ)結(jié)構(gòu)體
    let mut students: HashMap<u32, Student> = HashMap::new();
    
    students.insert(1, Student {
        name: String::from("Alice"),
        age: 20,
        grade: 85.5,
    });
    
    students.insert(2, Student {
        name: String::from("Bob"),
        age: 19,
        grade: 92.0,
    });
    
    // 訪問結(jié)構(gòu)體字段
    if let Some(student) = students.get(&1) {
        println!("學(xué)生姓名: {}", student.name);
    }
    
    // HashMap 存儲(chǔ) Vec
    let mut groups: HashMap<String, Vec<String>> = HashMap::new();
    
    groups.entry(String::from("Math")).or_insert(Vec::new())
        .push(String::from("Alice"));
    groups.entry(String::from("Math")).or_insert(Vec::new())
        .push(String::from("Bob"));
    
    println!("{:?}", groups);
}

7. 字符串作為鍵的注意事項(xiàng)

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    
    // 使用 String 作為鍵
    let key = String::from("hello");
    map.insert(key, 42);
    // println!("{}", key); // 錯(cuò)誤!key 已經(jīng)被移動(dòng)
    
    // 解決方案1: 克隆鍵
    let key2 = String::from("world");
    map.insert(key2.clone(), 24);
    println!("還可以使用 key2: {}", key2);
    
    // 解決方案2: 使用 &str 作為鍵類型
    let mut map2: HashMap<&str, i32> = HashMap::new();
    let text = "hello";
    map2.insert(text, 42);
    println!("還可以使用 text: {}", text);
    
    // 解決方案3: 使用引用插入(需要生命周期管理)
    let mut map3 = HashMap::new();
    let key3 = String::from("test");
    map3.insert(&key3, 42); // 插入引用
    println!("還可以使用 key3: {}", key3);
}

8. 實(shí)際應(yīng)用示例

use std::collections::HashMap;

// 計(jì)算單詞頻率
fn word_count(text: &str) -> HashMap<&str, usize> {
    let mut counts = HashMap::new();
    
    for word in text.split_whitespace() {
        let count = counts.entry(word).or_insert(0);
        *count += 1;
    }
    
    counts
}

// 分組操作
fn group_by_length(words: Vec<&str>) -> HashMap<usize, Vec<&str>> {
    let mut groups = HashMap::new();
    
    for word in words {
        groups.entry(word.len())
            .or_insert(Vec::new())
            .push(word);
    }
    
    groups
}

fn main() {
    // 單詞計(jì)數(shù)
    let text = "hello world hello rust world";
    let counts = word_count(text);
    for (word, count) in counts {
        println!("{}: {}", word, count);
    }
    
    // 按長度分組
    let words = vec!["cat", "dog", "elephant", "ant", "bear"];
    let groups = group_by_length(words);
    for (length, words) in groups {
        println!("長度 {}: {:?}", length, words);
    }
}

9. 性能提示

use std::collections::HashMap;

fn main() {
    // 1. 預(yù)分配容量以避免重新分配
    let mut map = HashMap::with_capacity(1000);
    
    // 2. 使用 entry API 避免重復(fù)查找
    // 好的做法
    *map.entry("key").or_insert(0) += 1;
    
    // 不好的做法(兩次查找)
    if map.contains_key("key") {
        let count = map.get_mut("key").unwrap();
        *count += 1;
    } else {
        map.insert("key", 1);
    }
    
    // 3. 批量操作
    let data = vec![("a", 1), ("b", 2), ("c", 3)];
    let map2: HashMap<_, _> = data.into_iter().collect();
}

這就是 Rust HashMap 的全面使用指南!HashMap 是處理鍵值對(duì)數(shù)據(jù)的強(qiáng)大工具,掌握這些用法可以讓你的 Rust 代碼更加高效。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容