首页 > 解决方案 > 带 HashMap 的缓存器

问题描述

按照第 13.1 章的建议,我尝试使用 HashMap 实现缓存器:

use std::collections::HashMap;

pub struct Cacher<T, U> 
where
    T: Fn(U) -> U,
    U: std::cmp::Eq + std::hash::Hash + Copy,
{
    calculation: T,
    values: HashMap<U, U>,
}

impl<T, U> Cacher<T, U> 
where
    T: Fn(U) -> U,
    U: std::cmp::Eq + std::hash::Hash + Copy,
{
    pub fn new(calculation: T) -> Cacher<T, U> {
        Cacher {
            calculation,
            values: HashMap::new(),
        }
    }

    pub fn value(&mut self, arg: U) -> &U{
        self.values.entry(arg).or_insert((self.calculation)(arg))
    }
}

但运行以下代码:

use cacher::Cacher;

fn main() {
    let mut cacher = Cacher::new(|arg|{
        println!("Executing for {:?}", arg);
        arg
    });
    assert_eq!(cacher.value(1), &1);
    assert_eq!(cacher.value(2), &2);
    assert_eq!(cacher.value(3), &3);
    assert_eq!(cacher.value(1), &1);
    assert_eq!(cacher.value(2), &2);
}

产生以下输出:

   Compiling cacher v0.1.0 (C:\Users\felix\Programming\rust\projects\Cacher)
    Finished dev [unoptimized + debuginfo] target(s) in 0.67s
     Running `target\debug\cacher.exe`
Executing for 1
Executing for 2
Executing for 3
Executing for 1
Executing for 2

显示缓存器不起作用,对每个值调用执行计算,即使是已知参数。价值函数出了什么问题

标签: rust

解决方案


即使密钥已经存在,看起来也正在调用该函数。

与以下代码fn value(&mut self, arg: U)相同的代码:

pub fn value(&mut self, arg: U) -> &U {
    let placeholder = (self.calculation)(arg);
    self.values.entry(arg).or_insert(placeholder)
}

因此,您可以改为使用 method .or_insert_with(),它允许您传递一个仅在密钥不存在时才调用的函数,如评论中发布的操场所示:

pub fn value(&mut self, arg: U) -> &U {
    let calculation = &self.calculation;
    self.values.entry(arg).or_insert_with(|| calculation(arg))
}

推荐阅读