Java: data structure for cache computation result?
I have an expensive computation whose result I would like to cache. Is there a way to make a card with two keys? I am thinking of something like Map<(Thing1, Thing2), Integer>
.
Then I could check:
if (! cache.contains(thing1, thing2)) {
return computeResult();
}
else {
return cache.getValue(thing1, thing2);
}
pseudocode. But something like that.
source to share
You need to create a class that contains Thing1 and Thing2, for example:
class Things {
public final Thing1 thing1;
public final Thing2 thing2;
public Things(Thing1 thing1, Thing2 thing2) {
this.thing1 = thing1;
this.thing2 = thing2;
}
@Override
public boolean equals(Object obj) { ... }
@Override
public int hashCode() { ... };
}
Then, to use it:
Things key = new Things(thing1, thing2);
if (!cache.contains(key) {
Integer result = computeResult();
cache.put(key, result);
return result;
} else {
return cache.getValue(key);
}
Please note that you must implement equals and hashcode for this code to work correctly. If you need this code to be thread safe, take a look at ConcurrentHashMap.
source to share
It looks like you want a memory. The last chapter of the torso, Functional Java has a type of memoising P1
that simulates a computation whose result is cached.
You would use it like this:
P1<Thing> myThing = new P1<Thing>() {
public Thing _1() {
return expensiveComputation();
}
}.memo();
Calling _1 () the first time will run an expensive computation and save it to a note. The reminder will then be saved instead.
For your "two keys" you need a simple pair type. Functional Java has this as a class too P2<A, B>
. To keep that amount, just use P1<P2<A, B>>
.
You can also use a class Promise<A>
instead of memoisation. This has been in the library for a while, so you just need the latest binary. You would use it like this:
Promise<Thing> myThing =
parModule(sequentialStrategy).promise(new P1<Thing>() {
public Thing _1() {
return expensiveComputation();
}
});
To get the result, just call myThing.claim()
. Promise<A>
also provides methods for displaying functions by result, even if the result is not yet ready.
You need import static fj.control.parallel.ParModule.parModule
and fj.control.parallel.Strategy.sequentialStrategy
. If you want the computation to run on its own thread, replace sequentialStrategy
with one of the other strategies provided by the class Strategy
.
source to share
If you are using Google Collections , its MapMaker
has a method makeComputingMap
that does exactly what you described. As a free bonus, it is also thread safe (implements ConcurrentMap
).
As for the two-key thing, you'll need to create a class that contains the two keys, and implement a suitable implementation equals
, hashCode
and (if applicable) compareTo
that makes the key compare how you want.
source to share