我在我的代码中有几个函数,使用记忆化(memoization)非常合适(甚至似乎是必要的)。
我不想为每个函数单独手动实现它。是否有一种方法(例如Python 中的),我可以只是使用一个注释或做其他事情,以便在那些我想要的函数上自动获得这个效果?
我在我的代码中有几个函数,使用记忆化(memoization)非常合适(甚至似乎是必要的)。
我不想为每个函数单独手动实现它。是否有一种方法(例如Python 中的),我可以只是使用一个注释或做其他事情,以便在那些我想要的函数上自动获得这个效果?
Spring 3.1 现在提供了一个 @Cacheable
注解,它可以标识可缓存的方法 - 也就是说,对于这些方法,它们的结果会被存储到缓存中,因此在后续调用(使用相同的参数)时,缓存中的值会被返回,而无需实际执行该方法。
正如名称所示,@Cacheable 用于标注可缓存的方法 - 也就是说,对于这些方法,它们的结果会被存储到缓存中,因此在后续调用(使用相同的参数)时,缓存中的值会被返回,而无需实际执行该方法。
我认为没有原生的记忆化语言实现。
但是,您可以将其作为方法的装饰器轻松实现。您需要维护一个映射:映射的键是参数,值是结果。
以下是一个简单的实现,适用于一个参数的方法:
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);
}
我发现了一个叫做Tek271的记忆化库,它似乎使用注释来像你描述的那样对函数进行记忆化。
您可以使用Function 接口在Google的guava库中轻松地实现您所需的功能:
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
您可以看到,第二次对参数2和1应用memoizedAdd2时,并没有实际运行apply中的计算,它只是获取存储的结果。
Cyclops 提供了函数、Suppliers、Callables、Predicates以及通过方法引用(via Method References)实现的扩展方法的Memoisation功能(请参见javadoc)。
例如:
给定一个名为“that”的变量,它记录我们的方法被调用的次数,我们可以看到Memoised函数只执行了一次该方法。
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;
}