我在我的代碼中有幾個函數,它使用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