guavas Cache(移位)的复合键

Mar*_*hke 8 java caching shift guava

我有一个点对象:

  class Point {
    final int x,y;
    ...
  }
Run Code Online (Sandbox Code Playgroud)

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

因为对象是由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);
    }
};
Run Code Online (Sandbox Code Playgroud)

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

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

bjm*_*jmi 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));
  }
}
Run Code Online (Sandbox Code Playgroud)

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

Point center = Points.cached(0, 0);
Run Code Online (Sandbox Code Playgroud)

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

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));
Run Code Online (Sandbox Code Playgroud)

  • 哎哟.非常糟糕的主意.首先,您将具有微小生命周期(所有垃圾收集器的小蛋糕)的对象转换为终身对象,使得所有未来的完整gc变慢.然后,这个东西变得无限,与内存泄漏没有多大区别.第三,只是为了在内存方面实现收支平衡,*所有缓存的点必须至少保留在两个地方*.只有当它们被重用时,才会有更多的内存保存.更不用说除了查找之外,不需要保留这些对象,更不用说保留在两个地方了.我会考虑删除这个答案: - \ (5认同)