guavas Cache(移位)的复合键

时间:2011-11-23 10:47:07

标签: java caching guava shift

我有一个点对象:

  class Point {
    final int x,y;
    ...
  }

因为这些点将在我的代码中的所有地方使用/创建,所以我想开始使用guavas缓存。遗憾的是,CacheLoader只接受一个参数。 stackoverflow上的Another question使用一对对象来解决类似的问题。但我不喜欢为每个缓存请求创建一个虚拟对象。 所以我想出了自己的解决方法:

因为对象是由x和y指定的,我想我可以将两个值合并(移位)为long,这将是我的关键。

void test(int x, int y) {
    Long key = (long) ((long) (x) << Integer.SIZE | y);
    Point point = cache.get(key);
}

CacheLoader<Long, Point> loader = new CacheLoader<Long, Point>() {
    public Point load(Long key) throws Exception {
    final int x,y;
        // shift magic
        x = (int) (key >> Integer.SIZE);
        y = key.intValue();
        return new Point(x, y);
    }
};

我实际上是一个转移菜鸟。这会有用吗?我错过了什么?这比同类“快”吗?这是我的问题!

是的,我测试了代码,到目前为止,我可以告诉它。

2 个答案:

答案 0 :(得分:8)

这个怎么样?您的Point类必须正确实现equals()hashcode()

static class Points {
  static final Interner<Point> INTERNER = Interners.newStrongInterner();

  public static Point cached(final int x, final int y) {
    return INTERNER.intern(new Point(x, y));
  }
}

你的实际目的是缓存相等的对象,对吧?比这更能满足您的需求。 用法:

Point center = Points.cached(0, 0);

或者缓存示例的调整后版本:

CacheLoader<Point, Point> loader = new CacheLoader<Point, Point>() {
  @Override
  public Point load(final Point point) {
    return point;
  }
}
...
Point center = cache.get(new Point(0, 0));

答案 1 :(得分:3)

它可能更快(如果差异是可测量的),但对类将使您的代码更好地理解或重用。我会选择通用的Pair类:

public final class Pair<L, R> {

    private final L left;
    private final R right;

    private Pair(L left, R right) {
        this.left = left;
        this.right = right;
    }

    public static <L,R>Pair<L,R> of(L left, R right){
        return new Pair<L, R>(left,right);
    }

    @Override
    public boolean equals(final Object obj) {
        if (obj instanceof Pair) {
            final Pair<?,?> other = (Pair<?,?>) obj;
            return Objects.equal(left,  other.left)
                && Objects.equal(right, other.right);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(left, right);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                      .add("left", left)
                      .add("right", right)
                      .toString();
    }

}

一旦你的代码库中有了这个,你会发现它有多个用途。比特转移并不像Java那样(尽管许多其他人不同意)。

Guava docs