Rust访问值为Option的HashMap时如何避免对返回值调用unwrap?
优化方案
你代码里的unwrap完全是不必要的,根源是你给HashMap的value套了一层多余的Option:你的所有插入操作都只会存入Some(计算结果),永远不会出现None的情况,直接把hmap的类型改为HashMap<u32, u32>就能直接删掉这个unwrap。
在此基础上,Rust针对HashMap「存在即返回、不存在则计算插入」的场景,提供了更符合惯用写法的entry API,无需手动写match分支,代码更简洁鲁棒。
优化后完整代码
use std::collections::HashMap; struct Cacher<T> { calculation: T, hmap: HashMap<u32, u32>, } impl<T> Cacher<T> where T: Fn(u32) -> u32, { fn new(calculation: T) -> Cacher<T> { Cacher { calculation, hmap: HashMap::new(), } } fn value(&mut self, arg: u32) -> u32 { // entry API直接处理命中/缺失逻辑,无需unwrap *self.hmap.entry(arg).or_insert_with(|| (self.calculation)(arg)) } } fn main() { let mut cache = Cacher::new(|x| x * x); let v = vec![cache.value(1), cache.value(2), cache.value(3)]; println!("v: {:?}", v); }
代码说明
entry方法会返回键对应的条目枚举,要么是已存在的Occupied,要么是不存在的Vacantor_insert_with方法会在条目为空时,调用传入的闭包计算值插入,最后返回条目的可变引用- 这里的解引用
*是为了拿到u32类型的返回值,符合原方法的返回签名
如果确实有场景需要在HashMap里存Option<u32>(比如要缓存的计算逻辑本身可能返回None),那也可以用嵌套模式匹配代替unwrap,写法如下:
// 仅针对必须存Option的场景的兼容写法 match self.hmap.get(&arg) { Some(Some(v)) => *v, _ => { let v = (self.calculation)(arg); self.hmap.insert(arg, Some(v)); v } }
这种写法完全避免了unwrap,就算后续你逻辑改成会存None也不会触发panic,鲁棒性更高。
内容的提问来源于stack exchange,提问作者magnusmaehlum
相关产品推荐
相关产品推荐

