我有一个点对象:
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);
}
};
我实际上是一个转移菜鸟。这会有用吗?我错过了什么?这比同类“快”吗?这是我的问题!
是的,我测试了代码,到目前为止,我可以告诉它。
答案 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那样(尽管许多其他人不同意)。