我有一个昂贵的计算,其结果我想缓存。有没有办法用两把钥匙制作地图?我在想Map<(Thing1, Thing2), Integer>
。
然后我可以检查:
if (! cache.contains(thing1, thing2)) {
return computeResult();
}
else {
return cache.getValue(thing1, thing2);
}
伪代码。但是就这些问题而言。
答案 0 :(得分:5)
您需要创建一个包含Thing1和Thing2的类,例如:
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() { ... };
}
然后使用它:
Things key = new Things(thing1, thing2);
if (!cache.contains(key) {
Integer result = computeResult();
cache.put(key, result);
return result;
} else {
return cache.getValue(key);
}
请注意,您必须实现equals和hashcode才能使此代码正常工作。如果您需要此代码是线程安全的,那么请查看ConcurrentHashMap。
答案 1 :(得分:3)
听起来你想要回忆。 Functional Java的最新主干头具有一个记忆产品类型P1
,用于对结果进行缓存的计算进行建模。
您可以这样使用它:
P1<Thing> myThing = new P1<Thing>() {
public Thing _1() {
return expensiveComputation();
}
}.memo();
第一次调用_1()将运行昂贵的计算并将其存储在备忘录中。之后,将返回备忘录。
对于“两把钥匙”,你需要一个简单的配对类型。功能Java也以类P2<A, B>
的形式提供此功能。要记住这样的值,只需使用P1<P2<A, B>>
。
您也可以使用Promise<A>
类而不是memoisation。这已经在库中了一段时间,所以你只需要最新的二进制文件。您可以按如下方式使用它:
Promise<Thing> myThing =
parModule(sequentialStrategy).promise(new P1<Thing>() {
public Thing _1() {
return expensiveComputation();
}
});
要获得结果,只需致电myThing.claim()
即可。 Promise<A>
还提供了在结果上映射函数的方法,即使结果尚未准备好。
您需要import static fj.control.parallel.ParModule.parModule
和fj.control.parallel.Strategy.sequentialStrategy
。如果您希望计算在其自己的线程中运行,请将sequentialStrategy
替换为Strategy
类提供的其他策略之一。
答案 2 :(得分:2)
如果您使用Google Collections,则其MapMaker
类会使用makeComputingMap
方法完全按照您的描述进行操作。作为免费奖励,它也是线程安全的(实现ConcurrentMap
)。
对于双键事项,您必须创建一个包含两个键的类,并实现equals
,hashCode
和(如果适用){{1}的合适实现以你想要的方式进行关键比较。