HashMap

hashmap

hashmap是一个无序的字典

创建hashmap

new

创建空的hashmap

use std::collections::HashMap;

fn main() {
  	// let mut map = HashMap::<String, i32>::new();
    let mut map:HashMap<String, i32> = HashMap::new();
    println!("{:?}", map);
}

with_capacity

创建一个具有指定最小容量的空 HashMap

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::with_capacity(10);

    for i in 1..=10 {
        map.insert(i, i * 10);
    };

    println!("{:?}", map);
}
{6: 60, 2: 20, 7: 70, 8: 80, 1: 10, 4: 40, 10: 100, 9: 90, 3: 30, 5: 50}

from

支持数组转hashmap,如果是VecIterator需要使用collect转换

use std::collections::HashMap;
use std::ptr::hash;

fn main() {
    let mut map = HashMap::from([("hello".to_string(), "world".to_string())]);
    println!("map: {:?}", map);

    let v: Vec<(&str, i32)> = vec![("a", 1), ("b", 2)];
    let mut map2: HashMap<&str, i32> = v.into_iter().collect();
    println!("map2: {:?}", map2);
}
map: {"hello": "world"}

迭代器创建hashmap

collect

use std::collections::HashMap;
use std::ptr::hash;

fn main() {
    let v: Vec<(&str, i32)> = vec![("a", 1), ("b", 2)];
    let mut map: HashMap<&str, i32> = v.into_iter().collect();
    println!("map: {:?}", map);
}
map: {"b": 2, "a": 1}

zip

两个vec压缩为Vec<(T, V)>,然后使用collect转为hashmap

use std::collections::HashMap;

fn main() {
    let teams = vec![String::from("Blue"), String::from("Yellow")];
    let initial_scores = vec![10, 50];
    let map: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();
    println!("map: {:?}", map);
}
map: {"Yellow": 50, "Blue": 10}

所有权转移问题

实现 Copy 特征,该类型会被复制进 HashMap

没实现 Copy 特征,所有权将被转移给 HashMap

fn main() {
    use std::collections::HashMap;

    let name = String::from("Sunface");
    let age = 18;

    let mut map = HashMap::new();
    map.insert(name, age);
    println!("map: {:?}", map);
    
    // name没有copy trait,所以无法使用
    // println!("因为过于无耻,{}已经被从帅气男孩名单中除名", name);
    println!("还有,他的真实年龄远远不止{}岁", age);
}
map: {"Sunface": 18}
还有,他的真实年龄远远不止18岁

使用引用类型

HashMap 中存储的引用类型,其指向的变量(被引用者)的生命周期必须严格大于 HashMap 本身的生命周期,否则会触发编译错误(悬垂引用)

fn main() {
    use std::collections::HashMap;

    let name = String::from("Sunface");
    let age = 18;

    let mut map = HashMap::new();
    map.insert(&name, age);
 		
    // 删除name
    drop(name);
		
    // 报错
    println!("map: {:?}", map);
}

插入值

insert

如果键已存在,会覆盖原有值,并返回被覆盖的旧值(Option<V>);如果键不存在,返回 None

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
  
    let old_value = map.insert("a".to_string(), 1);
    println!("old_value:{:?}", old_value); // None(首次插入无旧值)

    // 重复插入同一键:覆盖旧值,返回旧值
    let old_value2 = map.insert("a".to_string(), 10);
    println!("old_value2:{:?}", old_value2); // Some(1)
}
old_value:None
old_value2:Some(1)

entry

处理键存不存在的方式,返回Entry 枚举的 OccupiedVacant 两个变体

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert("one", 1);
    map.insert("two", 2);

    let s = map.entry("one");
    println!("{:?}", s);

    let s = map.entry("one1");
    println!("{:?}", s);
}
Entry(OccupiedEntry { key: "one", value: 1, .. })
Entry(VacantEntry("one1"))

显式匹配

需要使用use std::collections::hash_map::Entry;

use std::collections::HashMap;
use std::collections::hash_map::Entry;

fn main() {
    let mut map = HashMap::new();
    map.insert("one", 1);
    map.insert("two", 2);
		
  	// map中已经存在了one
    let s = map.entry("one");
    match s {
        // 键存在
        Entry::Occupied(mut occupied) => {
            let k = occupied.get_mut();
            *k += 1;
        }
        // 键不存在
        Entry::Vacant(vacant) => {
            vacant.insert(1);
        }
    }

		
		// map中不存在ccc键
    let s = map.entry("ccc");
    match s {
        // 键存在
        Entry::Occupied(mut occupied) => {
            let k = occupied.get_mut();
            *k += 1;
        }
        // 键不存在
        Entry::Vacant(vacant) => {
            vacant.insert(1);
        }
    }

    println!("{:?}", map);
}
{"one": 2, "ccc": 1, "two": 2}
Entry::Occupied值存在
  • get_mut和into_mut区别
    • get_mut仍可继续调用其他方法(如 get()insert()
    • into_mut无法再使用该 Occupied(已被消耗)
Occupied方法 作用
get(&self) 获取现有值的不可变引用&V),只能读不能改
get_mut(&mut self) 获取现有值的可变引用&mut V),可修改值
into_mut(self) 消耗 OccupiedEntry,返回值的可变引用&mut V
insert(&mut self, V) 覆盖现有值,返回被替换的旧值V
remove(self) 移除该键值对,返回被移除的值V
Entry::Vacant值不存在
Vacant方法 作用
key(&self) 获取待插入的的不可变引用(&K)(仅能读键,无值可操作)
into_key(self) 消耗 VacantEntry,返回待插入的键的所有权K
insert(self, V) 插入指定值到空位,返回新插入值的可变引用&mut V
insert_with<F>(self, f: F) 通过闭包生成值并插入,返回新值的可变引用(&mut F::Output

entry()+or_insert()

如果key不存在就插入

如果key存在,返回对已有值的可变引用(&mut V

底层就是VacantEntry+ insert

use std::collections::HashMap;

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

    map.insert(String::from("a"), 1);
    map.insert(String::from("b"), 2);
    map.insert(String::from("c"), 3);

    map.entry(String::from("d")).or_insert(4);
    // 存在返回
    let s = map.entry(String::from("a")).or_insert(11);
    *s += 1;
    println!("{:?}", map);
}
{"c": 3, "a": 2, "d": 4, "b": 2}

entry(key).or_default()

or_insert 的特化版本。如果键不存在,则插入该类型的默认值(即实现 Default trait 的值,如 0, "", Vec::new())。

use std::collections::HashMap;

fn main() {
    let mut map:HashMap<&str, i32> = HashMap::new();

    let s = "b,a,b,a,b,s,h,d";
    for c in s.split(",") {
      	// let count = map.entry(c).or_default();
      	// *count += 1;
        *map.entry(c).or_default() += 1;
    }
    println!("{:?}", map);
}
{"a": 2, "h": 1, "d": 1, "s": 1, "b": 3}

entry().and_modify().or_insert()

and_modify仅当键存在时操作值,相比操作Occupied,可以链式调用

相当于Occupied + get_mut()

use std::collections::HashMap;

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

    map.entry("key")
        .and_modify(|e| *e += 5) // 存在时加 5
        .or_insert(10); // 不存在时插入 10

    println!("map: {:?}", map);
    map.entry("key")
        .and_modify(|e| *e *= 2) // 存在时乘以 2
        .or_insert(20); // 不会执行(键已存在)

    println!("map: {:?}", map);
}
map: {"key": 10}
map: {"key": 20}

entry()+or_insert_with()

和or_insert区别是,or_insert是立即创建值(饿汉式),or_insert_with是惰性创建值

  • or_insert(V)
    • 简单类型(如 i32bool&str),创建成本几乎为 0
  • or_insert_with(F)
    • 创建成本高(比如 StringVec、自定义结构体、需要计算 / IO 生成的值)
use std::collections::HashMap;

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

    map.insert("s", 2);
    // 键存在也会创建3
    map.entry("s").or_insert(3);
    
    // or_insert_with 键存在不会调用
    map.entry("s").or_insert_with(|| {println!("创建了11"); 3});
    map.entry("m").or_insert_with(|| {println!("创建了22"); 3});
    println!("{:?}", map);
}
创建了22
{"m": 3, "s": 2}

删除key

remove

仅被移除的值(所有权);键不存在返回 None

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert("a", 1);
    map.insert("b", 2);


    let s1 = map.remove("a");
    println!("s1: {:?}", s1);
    let s2 = map.remove("aa");
    println!("s2: {:?}", s2);

    println!("map: {:?}", map);
}
s1: Some(1)
s2: None
map: {"b": 2}

remove_entry

被移除的键 + 值(所有权);键不存在返回 None

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert("a", 1);
    map.insert("b", 2);


    let s1 = map.remove_entry("a");
    println!("s1: {:?}", s1);
    let s2 = map.remove_entry("aa");
    println!("s2: {:?}", s2);

    println!("map: {:?}", map);
}
s1: Some(("a", 1))
s2: None
map: {"b": 2}

检查值是否存在

contains_key

返回bool值,检测值是否存在

use std::collections::HashMap;

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

    map.insert("s", 2);
    // 键存在,不做任何事
    // 键不存在,value设置3
    map.entry("s").or_insert(3);

    let s = map.contains_key("s");
    println!("{:?}", s);
    println!("{:?}", map);
}
true
{"s": 2}

获取所有key值

keys

借用 HashMap(&self),不消耗map自身

use std::collections::HashMap;

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

    map.insert("a", 1);
    map.insert("b", 2);
    map.insert("c", 3);
    let s: Vec<_> = map.keys().collect();
    println!("{:?}", s);
}
["b", "c", "a"]

into_keys

消耗map,转移所有权

use std::collections::HashMap;

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

    map.insert("a", 1);
    map.insert("b", 2);
    map.insert("c", 3);
    let s: Vec<_> = map.into_keys().collect();
    println!("{:?}", s);
}
["c", "a", "b"]

获取所有value值

values

keys一样,获取引用,不消耗map

use std::collections::HashMap;

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

    map.insert("a", 1);
    map.insert("b", 2);
    map.insert("c", 3);
    let s: Vec<_> = map.values().collect();
    println!("{:?}", s);
    println!("{:?}", map);
}
[1, 3, 2]

into_values

获取所有权,调用之后不能再使用map了

use std::collections::HashMap;

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

    map.insert("a", 1);
    map.insert("b", 2);
    map.insert("c", 3);
    let s: Vec<_> = map.into_values().collect();
    println!("{:?}", s);
}
[3, 1, 2]

判断是否是空字典is_empty

返回bool值

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    println!("{}", map.is_empty());
    map.insert("a", 1);
    map.insert("b", 2);
    println!("{}", map.is_empty());
}
true
false

获取值

get

返回Option<&V>,仅读取值,不修改,键不存在返回 None

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert("a", 1);
    map.insert("b", 2);
    println!("{:?}", map.get("a"));
    println!("{:?}", map.get("c"));
}
Some(1)
None

get_mut

返回Option<&mut V>,需要修改已存在的值键,不存在返回 None

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert("a", 1);
    map.insert("b", 2);

    if let Some(v) = map.get_mut("a") {
        *v += 3
    } else {
        println!("a 不存在");
    };

    if let Some(v) = map.get_mut("c") {
        *v += 3
    } else {
        println!("c 不存在");
    };

    println!("{:?}", map);
}
c 不存在
{"b": 2, "a": 4}

获取长度len

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert("a", 1);
    map.insert("b", 2);

    println!("{:?}", map.len());
}
2

创建迭代器

iter

只读遍历(无法修改值)

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert("a", 1);
    map.insert("b", 2);


    for (k, v) in map.iter() {
        println!("k: {}, v: {}", k, v);
    }
}
k: b, v: 2
k: a, v: 1

iter_mut

可修改值(键仍不可改)

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert("a", 1);
    map.insert("b", 2);


    for (k, v) in map.iter_mut() {
        println!("k: {}, v: {}", k, v);
      	// 解引用修改value值
        *v += 10;
    };

    println!("map: {:?}", map);
}
k: b, v: 2
k: a, v: 1
map: {"b": 12, "a": 11}
posted @ 2026-04-14 02:09  lxd670  阅读(8)  评论(0)    收藏  举报