我在我的代码中有几个函数,它使用memoization有很大的意义(甚至是强制性的)。Java:自动记忆
我不想为每个功能单独手动实现。是否有某种方法(例如like in Python)我可以只使用一个注释或做其他事情,这样我就可以在需要它的那些函数上自动获取它?
我在我的代码中有几个函数,它使用memoization有很大的意义(甚至是强制性的)。Java:自动记忆
我不想为每个功能单独手动实现。是否有某种方法(例如like in Python)我可以只使用一个注释或做其他事情,这样我就可以在需要它的那些函数上自动获取它?
Spring 3.1现在提供了一个@Cacheable
annotation,它完全是这样。
顾名思义,@Cacheable用于区分是缓存的方法 - 那就是,方法对他们来说,结果被存入缓存,以便在后续调用(使用相同的参数),在价值缓存被返回而不必实际执行该方法。
我不认为有一种语言本地实现memoization。
但是你可以很容易地实现它,作为你的方法的装饰器。你必须保持一个Map:你的Map的关键是参数,值是结果。
下面是一个简单的实现,对于一个带参数的方法:
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);
}
您可以使用Function接口谷歌的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
将2添加到:2
添加2〜3
添加2至4
你可以看到,第二时间memoizedAdd2被调用(应用)到参数2和1,应用程序中的计算实际上并未运行,只是取得了存储的结果。
来得更接近我想要什么,但还是太具体被发现。是否有可能对此进行更广义的描述,以便可以使用任意数量的参数(而不仅仅是一个)? – Albert 2010-10-15 09:12:38
Guava的Function类将所有输入浓缩为一个参数。现在,这个论点的类型可以是一个Object [],它可以有效地允许任何事情,但会降低类型检查的有效性。或者说,这将是非常简单的创建由
番石榴的供应商类具有内置的memoize的和memoizeWithExpiration方法。 – lbalazscs 2015-03-20 00:04:05
Cyclops提供Memoisation的功能,供应商,可调用,谓词和扩展方法(通过方法引用)(see javadoc)
例如
给定一个所谓的可变计数的时间我们的方法其实就是所谓的号码,我们可以看到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;
}
我怎样才能以通用的方式实现它作为我的方法的装饰器? – Albert 2010-10-14 15:38:49
@Albert:作为伯努瓦表示,没有本地实现这一点(即你不能在没有Java的黑客一般的方式做到这一点),因为蟒蛇装饰材料使用了一些“元信息”有关的功能。即python可以让修饰器修改原始函数。这是 - 据我所知 - 在Java中不可能。 – phimuemue 2010-10-14 15:44:41
“你可以很容易地实现它,作为你的方法的装饰器。” < - 我怎样才能做到装饰者?或者你是什么意思? – Albert 2010-10-14 15:46:11