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
相关产品推荐
相关产品推荐

