I have a point object:
class Point {
final int x,y;
...
}
Because these points will be used/created all over the place in my code, I want to start using guavas cache. Unfortuinally the CacheLoader only accept one parameter. Another question here on stackoverflow use a pair object for a similar problem. But I don't like the idea to create a dummy object for every cache request. So I come up with my own workaround:
Because the object is specified by the x and y, I think I can merge(shift) both values into a long, which will be my key.
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);
}
};
I'm actually a shift noob. Will this work? Did I miss something? Is this "faster" than the pair class? That's my question!
Yes, I test the code and it works so far I can tell.
Hazelcast is for distributed caching, meaning many services share the same cache, whereas Guava/Caffeine is a local cache per each service (not shared).
Guava provides a very powerful memory based caching mechanism by an interface LoadingCache<K,V>. Values are automatically loaded in the cache and it provides many utility methods useful for caching needs.
Guava Cache is an in-memory cache used in applications. The following operations can be performed on a cache: Insert data.
Guava Caches store values in RAM.
How about this? Your Point class must correctly implement equals()
and 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));
}
}
Your actual purpose was to cache equal objects, right? Than this will suffice your needs. Usage:
Point center = Points.cached(0, 0);
Or an adjusted version of your cache example:
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));
It's probably faster (if the difference is measurable at all), but the pair class will make your code much better to understand or reuse. I'd go with a generic Pair class:
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();
}
}
Once you have that in your code base, you will find more than one use for it. Bit shifting is not really Java-like (although many others will disagree).
Guava docs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With