在我的情况下,CacheBuilder可以取代MapMaker吗?

时间:2011-09-30 20:51:38

标签: java caching guava

我需要为类slowResult()的实例获取慢速方法Something的结果。单独缓存并没有帮助,因为实例几乎不会重复。幸运的是,我知道结果实际上只取决于一些容易获得的Attributes Something,所以我可以在代码中使用Map<Attributes, Result>作为缓存

Result fastResult(Something something) {
    final Attributes attributes = attributesFor(something)
    Result result = cache.get(attributes);
    if (result!=null) return result;
    result = something.slowResult();
    cache.put(attributes, result);
    return result;
}

为了保持缓存有限,我使用了现已弃用的方法maximumSizeexpireAfterAccess。弃用是因为要使用新的类CacheBuilder。但是,我发现如何将它应用到我的案例中的方法并不好。缓存键需要是Attributes的实例,但在缓存加载中需要Something的实例,并且没有简单的方法可以从Attributes重新创建它。

这个问题有好的解决方案吗?

3 个答案:

答案 0 :(得分:3)

非常有趣!我认为我们没有听说过这样的案例。

对于11.0,您将能够cache.asMap().put(),因此暂时忽略弃用警告可能是可以的。我们正在考虑可能在10.1补丁版本中启用它,因为几个用户似乎在类似的船上。

但是,在11.0中,我们正在努力的另一个想法是允许你这样做:

Result fastResult(final Something something) {
  return cache.get(
      attributesFor(something),
      new Callable<Result>() {
        public Result call() {
          return something.slowResult();
        }
      });
}

答案 1 :(得分:0)

您可以直接关闭Cache of Something吗?

答案 2 :(得分:0)

好吧,说明这个问题的一种方法是,“我如何比较Attributes.equals()缓存,但仍然可以访问Something来创建值”。所以,我认为这可能有用......

class SomethingKey {
  private Something something;
  private final Attributes attributes;
  SomethingKey(Something s) {
    this.something = s;
    this.attributes = attributesFor(something);
  }
  public Result createResult() {
    Something something = this.s;
    this.s = null;
    return something.slowResult();
  }
  public boolean equals(Object o) {
    if(o==this) return true;
    if(o==null || o.getClass() != this.getClass) return false;
    SomethingKey that = (SomethingKey)o;
    return this.attributes.equals(that.attributes);
  }
}

然后CacheLoader.load基本上是

Result load(SomethingKey k) {
   return k.createResult();
}

地图将是

Cache<SomethingKey,Result> map = ...;

当然,缺点是你要为每个请求创建一个新的SomethingKey,但是......