我有一个昂贵的计算,我想缓存它的结果。有没有办法用两个键制作地图?我在想类似的东西Map<(Thing1, Thing2), Integer>
。
然后我可以检查:
if (! cache.contains(thing1, thing2)) {
return computeResult();
}
else {
return cache.getValue(thing1, thing2);
}
伪代码。但是有些类似的东西。
我有一个昂贵的计算,我想缓存它的结果。有没有办法用两个键制作地图?我在想类似的东西Map<(Thing1, Thing2), Integer>
。
然后我可以检查:
if (! cache.contains(thing1, thing2)) {
return computeResult();
}
else {
return cache.getValue(thing1, thing2);
}
伪代码。但是有些类似的东西。
您需要创建一个包含 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。
听起来你想要记忆。最新的函数式 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>
类而不是记忆。这在库中已经有一段时间了,所以你只需要最新的二进制文件。您可以按如下方式使用它:
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
如果您使用Google Collections,它的MapMaker
类有一个makeComputingMap
完全按照您描述的方法。作为免费奖励,它也是线程安全的(实现ConcurrentMap
)。
至于两个键的东西,您将必须创建一个包含两个键的类,并实现一个合适的equals
、hashCode
和 (如果适用)compareTo
实现,以您想要的方式进行键比较。