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.

+2


source to share


3 answers


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.

+5


source


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

.

+3


source


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.

+2


source







All Articles