我的代码中有一些函数,使用 memoization 很有意义(似乎甚至是强制性的)。
我不想分别为每个功能手动实现。有什么方法(例如在 Python 中)我可以只使用注释或做其他事情,所以我可以在我想要的那些函数上自动获得它?
我的代码中有一些函数,使用 memoization 很有意义(似乎甚至是强制性的)。
我不想分别为每个功能手动实现。有什么方法(例如在 Python 中)我可以只使用注释或做其他事情,所以我可以在我想要的那些函数上自动获得它?
Spring 3.1 现在提供了一个@Cacheable
annotation,它正是这样做的。
顾名思义,@Cacheable 用于划分可缓存的方法 - 即,将结果存储到缓存中的方法,因此在后续调用(使用相同的参数)时,无需返回缓存中的值实际执行该方法。
我遇到了一个名为Tek271的记忆库,它似乎使用注释来记忆你所描述的功能。
我不认为有记忆化的语言本机实现。
但是你可以很容易地实现它,作为你方法的装饰器。你必须维护一个地图:你的地图的关键是参数,值是结果。
这是一个简单的实现,用于单参数方法:
Map<Integer, Integer> memoizator = new HashMap<Integer, Integer>();
public Integer memoizedMethod(Integer param) {
if (!memoizator.containsKey(param)) {
memoizator.put(param, method(param));
}
return memoizator.get(param);
}
您可以使用Google番石榴库中的Function接口轻松实现您的目标:
import java.util.HashMap;
import java.util.Map;
import com.google.common.base.Function;
public class MemoizerTest {
/**
* Memoizer takes a function as input, and returns a memoized version of the same function.
*
* @param <F>
* the input type of the function
* @param <T>
* the output type of the function
* @param inputFunction
* the input function to be memoized
* @return the new memoized function
*/
public static <F, T> Function<F, T> memoize(final Function<F, T> inputFunction) {
return new Function<F, T>() {
// Holds previous results
Map<F, T> memoization = new HashMap<F, T>();
@Override
public T apply(final F input) {
// Check for previous results
if (!memoization.containsKey(input)) {
// None exists, so compute and store a new one
memoization.put(input, inputFunction.apply(input));
}
// At this point a result is guaranteed in the memoization
return memoization.get(input);
}
};
}
public static void main(final String[] args) {
// Define a function (i.e. inplement apply)
final Function<Integer, Integer> add2 = new Function<Integer, Integer>() {
@Override
public Integer apply(final Integer input) {
System.out.println("Adding 2 to: " + input);
return input + 2;
}
};
// Memoize the function
final Function<Integer, Integer> memoizedAdd2 = MemoizerTest.memoize(add2);
// Exercise the memoized function
System.out.println(memoizedAdd2.apply(1));
System.out.println(memoizedAdd2.apply(2));
System.out.println(memoizedAdd2.apply(3));
System.out.println(memoizedAdd2.apply(2));
System.out.println(memoizedAdd2.apply(4));
System.out.println(memoizedAdd2.apply(1));
}
}
应该打印:
将 2 添加到: 1
3
将 2 添加到:2
4
将 2 添加到: 3
5
4
将 2 添加到:4
6
3
您可以看到第二次 memoizedAdd2 被调用(应用)到参数 2 和 1,apply 中的计算实际上并没有运行,它只是获取存储的结果。
Cyclops为函数、供应商、可调用对象、谓词和扩展方法提供记忆(通过方法引用)(参见 javadoc)
例如
给定一个变量来计算我们的方法被实际调用的次数,我们可以看到被记忆的函数实际上只执行了一次方法。
int called = 0;
cached = Memoise.memoiseQuadFunction(this::addAll);
assertThat(cached.apply(1,2,3,4),equalTo(10));
assertThat(cached.apply(1,2,3,4),equalTo(10));
assertThat(called,equalTo(1));
private int addAll(int a,int b,int c, int d){
called++;
return a+b+c+d;
}