You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust新手疑问:HashMap的or_insert为何会调用闭包?

Rust HashMap entry.or_insert 闭包执行问题解惑

嘿,我刚看完你的问题,其实你对or_insert的理解差了一点点——问题出在参数的求值时机上,不是你想的那样哦!

你现在写的代码里,(closure)(arg)是立即求值的,也就是说,不管entry里有没有对应的键,这个表达式都会先被计算出来,再把结果传给or_insert方法。哪怕entry已经存在,你调用(closure)(arg)的时候,那个复杂操作已经执行完了,这就是为什么第二次调用result(10)时,还是会打印“正在执行复杂操作.....”。

你真正需要的是or_insert_with方法,这个方法才会在entry不存在的时候才去执行传入的闭包。把你的代码修改一下:

use std::collections::HashMap;
use std::thread;
use std::time::Duration;

struct Cacher {
    result: HashMap<u32, u32>,
}
impl Cacher {
    fn new() -> Cacher {
        Cacher{ result: HashMap::new() }
    }
    fn result(&mut self, arg: u32) -> u32 {
        match self.result.get(&arg) {
            Some(v) => println!("已有值 {} 对应参数 {}", v, arg),
            None => println!("无对应值 {}", arg)
        }
        let v = self.result.entry(arg).or_insert_with(|| {
            println!("正在执行复杂操作.....");
            thread::sleep(Duration::from_secs(2));
            arg + 42
        });
        *v
    }
}
fn main() {
    let mut business_logic = Cacher::new();
    business_logic.result(10);
    business_logic.result(10);
}

这里再给你明确一下两个方法的核心区别:

  • or_insert(value):传入的value会被立即计算,不管entry是否存在,这个计算过程都会发生
  • or_insert_with(closure):传入的闭包只会在entry不存在的时候才会被调用执行

修改之后再运行代码,你会看到第二次调用result(10)时,只会打印“已有值 52 对应参数 10”,不会再执行那个耗时的复杂操作,完全符合你的预期啦!

内容的提问来源于stack exchange,提问作者chopchop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:02:29