私のコードには、メモ化を使用することが非常に理にかなっている (必須でさえあるように思える) いくつかの関数があります。
関数ごとに個別に手動で実装したくありません。何らかの方法がありますか (たとえば、 Python のように)、注釈を使用するか、他のことを行うことができるので、必要な関数でこれを自動的に取得できますか?
私のコードには、メモ化を使用することが非常に理にかなっている (必須でさえあるように思える) いくつかの関数があります。
関数ごとに個別に手動で実装したくありません。何らかの方法がありますか (たとえば、 Python のように)、注釈を使用するか、他のことを行うことができるので、必要な関数でこれを自動的に取得できますか?
Spring 3.1 は、まさにこれを行う@Cacheable
アノテーションを提供するようになりました。
名前が示すように、 @Cacheable は、キャッシュ可能なメソッド、つまり、結果がキャッシュに格納されるメソッドを区別するために使用されます。そのため、後続の呼び出し (同じ引数を使用) では、キャッシュ内の値が返されます。実際にメソッドを実行します。
あなたが説明したように、アノテーションを使用して関数をメモ化しているように見えるTek271というメモ化ライブラリに出会いました。
メモ化の言語ネイティブ実装はないと思います。
ただし、メソッドのデコレータとして簡単に実装できます。マップを維持する必要があります。マップのキーはパラメーターであり、値は結果です。
引数が 1 つのメソッドの簡単な実装を次に示します。
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 のguavaライブラリの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 に追加: 2
4
2 を 3 に追加
5
4
2 を追加: 4
6
3
2 回目に memoizedAdd2 が引数 2 と 1 に呼び出された (適用された) ことがわかります。適用の計算は実際には実行されず、格納された結果を取得しただけです。