Je connais celui-ci http://onjava.com/pub/a/onjava/2003/08/20/memoization.html mais y a-t-il autre chose?Quelles sont les différentes techniques de mémoisation en Java?
Répondre
Memoization est aussi facile avec typesafe simple, plaine de Java.
Vous pouvez le faire à partir de rien avec les classes réutilisables suivantes.
Je les utilise comme des caches dont la durée de vie est la demande sur une webapp.
Bien sûr, utilisez le Guava MapMaker
si vous avez besoin d'une stratégie d'éviction ou d'autres fonctionnalités comme la synchronisation.
Si vous devez mémoriser une méthode avec de nombreux paramètres, placez simplement les paramètres dans une liste avec les deux techniques et transmettez cette liste en tant que paramètre unique.
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);
}
Et ceci est utilisé comme celui-ci
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);
Goyave n'est pas encore approuvé pour notre environnement, logiciel financier ... – ranv01
Goyave n'est pas encore approuvé pour notre environnement. Logiciel bancaire ... Mais cela fera l'affaire. Je vais limiter la taille de la carte pour éviter les fuites de mémoire. Je ne m'inquiète pas des expulsions puisque ceci sera conservé seulement pendant l'invocation d'une méthode. – ranv01
J'aime la façon dont le code hautement testé n'est pas approuvé, mais quelque chose collé sur SO est :) –
Oui. Utilisez caches à partir de Guava.
Exemple:
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));
}
}
}
MapMaker est maintenant obsolète en faveur de CacheBuilder: https://code.google.com/p/guava-libraries/wiki/MapMakerMigration – dzieciou
@dzieciou J'ai enfin mis à jour le code pour quelque chose qui fonctionne avec le dernier Goyave (18.0 at l'heure actuelle de l'écriture). Et cette fois, c'est testé! –
Pour memoize fonctions sans paramètres, utilisez Suppliers.memoize(Supplier)
de goyave. Pour les fonctions avec paramètres, utilisez CacheBuilder.build(CacheLoader)
avec des objets de valeur de paramètre en tant que clés.
Cet exemple effectue une mémoisation sur toutes les méthodes d'un objet via un proxy. Mais la mémo typique est une fonction à la fois. Cette technique de proxy serait ennuyante quand vous ne voulez pas mémoriser toutes les méthodes d'un objet. – lacroix1547