web-dev-qa-db-ja.com

Javaでメモ化するためのさまざまな手法は何ですか?

私はこれを知っています http://onjava.com/pub/a/onjava/2003/08/20/memoization.html しかし、他に何かありますか?

23
ranv01

プレーンでシンプルなタイプセーフJavaを使用すると、メモ化も簡単です。

次の再利用可能なクラスを使用して、最初からそれを行うことができます。

私はこれらをキャッシュとして使用し、その存続期間はWebアプリでのリクエストです。

もちろん、エビクション戦略や同期などの機能が必要な場合は、Guava MapMakerを使用してください。

多くのパラメーターを含むメソッドをメモ化する必要がある場合は、両方の手法を使用してパラメーターをリストに入れ、そのリストを単一のパラメーターとして渡します。

abstract public class Memoize0<V> {
    //the memory
    private V value;
    public V get() {
        if (value == null) {
            value = calc();
        }
        return value;
    }
    /**
     * will implement the calculation that 
     * is to be remembered thanks to this class
     */
    public abstract V calc();
}

abstract public class Memoize1<P, V> {
    //The memory, it maps one calculation parameter to one calculation result
    private Map<P, V> values = new HashMap<P, V>();

    public V get(P p) {
        if (!values.containsKey(p)) {
            values.put(p, calc(p));
        }
        return values.get(p);
    }

    /**
     * Will implement the calculations that are
     * to be remembered thanks to this class
     * (one calculation per distinct parameter)
     */
    public abstract V calc(P p);
 }

そしてこれはこのように使用されます

    Memoize0<String> configProvider = new Memoize0<String>() {
        @Override
        public String calc() {
            return fetchConfigFromVerySlowDatabase();
        }
    };
    final String config = configProvider.get();

    Memoize1<Long, String> usernameProvider = new Memoize1<Long, String>() {
        @Override
        public String calc(Long id) {
            return fetchUsernameFromVerySlowDatabase(id);
        }
    };
    final String username = usernameProvider.get(123L);
14
lacroix1547

パラメータなしで関数をメモ化するには、Guavaの Suppliers.memoize(Supplier) を使用します。パラメータを持つ関数の場合、パラメータ値オブジェクトをキーとして CacheBuilder.build(CacheLoader) を使用します。

20
thSoft

はい。 caches from Guava を使用します。

例:

import Java.math.BigInteger;

import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

public class Fibonacci {
    private static final LoadingCache<Integer, BigInteger> CACHE
            = CacheBuilder.newBuilder().build(CacheLoader.from(Fibonacci::fib));

    public static BigInteger fib(int n) {
        Preconditions.checkArgument(n >= 0);
        switch (n) {
        case 0:
            return BigInteger.ZERO;
        case 1:
            return BigInteger.ONE;
        default:
            return CACHE.getUnchecked(n - 1).add(CACHE.getUnchecked(n - 2));
        }
    }
}
16