首页 > 解决方案 > 如何更新 HashMap 中的键?

问题描述

我找不到任何方法可以让我更新 a 的密钥HashMap。有get_key_value,但它返回一个不可变引用而不是可变引用。

标签: rusthashmapkey

解决方案


一般1不能。从HashMap文档中:

以这样一种方式修改键是一个逻辑错误,即键的哈希(由Hashtrait 确定)或它的相等性(由Eqtrait 确定)在映射中发生变化。这通常只能通过CellRefCell、全局状态、I/O 或不安全代码实现。

相反,删除该值并重新插入它:

use std::{collections::HashMap, hash::Hash};

fn rename_key<K, V>(h: &mut HashMap<K, V>, old_key: &K, new_key: K)
where
    K: Eq + Hash,
{
    if let Some(v) = h.remove(old_key) {
        h.insert(new_key, v);
    }
}

也可以看看:


1 — 如文档所述,可以对其进行修改,只要您不更改密钥的散列或比较方式。这样做会导致HashMap处于无效状态。

正确执行此操作的示例(但原因仍然令人怀疑):

use std::{
    cell::RefCell,
    collections::HashMap,
    hash::{Hash, Hasher},
    sync::Arc,
};

#[derive(Debug)]
struct Example<A, B>(A, B);

impl<A, B> PartialEq for Example<A, B>
where
    A: PartialEq,
{
    fn eq(&self, other: &Self) -> bool {
        self.0 == other.0
    }
}

impl<A, B> Eq for Example<A, B> where A: Eq {}

impl<A, B> Hash for Example<A, B>
where
    A: Hash,
{
    fn hash<H>(&self, h: &mut H)
    where
        H: Hasher,
    {
        self.0.hash(h)
    }
}

fn main() {
    let mut h = HashMap::new();
    let key = Arc::new(Example(0, RefCell::new(false)));

    h.insert(key.clone(), "alpha");
    dbg!(&h);

    *key.1.borrow_mut() = true;
    dbg!(&h);
}

您可以使用其他技术来获取对密钥的可变引用,例如不稳定的raw_entry_mut(如Sven Marnach 所述)。


推荐阅读