开发者

Can CacheBuilder replace MapMaker in my case?

开发者 https://www.devze.com 2023-04-10 10:07 出处:网络
I need to obtain the result of the slow method slowResult() for instances of the class Something. Caching alone doesn\'t help as the instances hardly ever repeat. Fortunately, I know that the result d

I need to obtain the result of the slow method slowResult() for instances of the class Something. Caching alone doesn't help as the instances hardly ever repeat. Fortunately, I know that the result depends actually only on some easily obtained Attributes of Something, so I could use a Map<Attributes, Result> as a cache, in code

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;
}

In order to keep the cache limited I used the now deprecated methods maximumSize and expireAfterAccess. The deprecation comes because of the new class CacheBuilder to be used instead. However, I've found no nice way how to apply it to my case. The cache keys need to be instances of Attributes, but in cache loading an instance of Something is neede开发者_运维百科d and there's no easy way to recreate it from the Attributes.

Is there a nice solution to this problem?


Very interesting! I don't think we had ever heard of a case like this.

For 11.0 you'll be able to do cache.asMap().put(), so it would probably be okay to just ignore the deprecation warnings for now. We are considering possibly enabling that in a 10.1 patch release because several users seem to be in a similar boat.

But, in 11.0 the other idea we're kicking around would allow you to do this:

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


Well, one way to state this problem is, "how can I compare Attributes.equals() for the cache, but still have access to Something to create the value". So, I think this might work ...

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);
  }
}

And then CacheLoader.load is basically

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

And the map would be

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

Of course, the downside is you're creating a new SomethingKey per request, but...


Can you just key the Cache off of Something instead?

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号