So di questo uno http://onjava.com/pub/a/onjava/2003/08/20/memoization.html ma c'è qualcos'altro?Quali sono le diverse tecniche di memoizzazione in Java?
risposta
Memoizzazione è anche facile con la pianura semplice typesafe Java.
si può fare da zero con le seguenti classi riutilizzabili.
io uso questi come cache la cui durata di vita sono la richiesta su una webapp.
Ovviamente utilizzare Guava MapMaker
se è necessaria una strategia di sfratto o più funzioni come la sincronizzazione.
Se è necessario memoizzare un metodo con molti parametri, è sufficiente mettere i parametri in un elenco con entrambe le tecniche e passare tale elenco come parametro singolo.
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);
}
E questo è usato come questo
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);
Guava non è ancora stato approvato per il nostro ambiente, software finanziario ... – ranv01
Guava non è ancora stato approvato per il nostro ambiente. Software bancario ... Ma questo lo farà. Limiterò comunque la dimensione della mappa per evitare perdite di memoria. Non mi preoccupo degli sfratti poiché questo sarà conservato solo durante l'invocazione di un metodo. – ranv01
Mi piace il modo in cui il codice altamente testato non è approvato, ma qualcosa incollato su SO è :) –
Sì. Utilizzare caches da Guava.
Esempio:
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 è ora obsoleto in favore di CacheBuilder: https://code.google.com/p/guava-libraries/wiki/MapMakerMigration – dzieciou
@dzieciou Ho finalmente aggiornato il codice a qualcosa che funziona con l'ultimo Guava (18.0 a ora attuale della scrittura). E questa volta, è testato! –
Per Memoize funzioni senza parametri, utilizzare Guava di Suppliers.memoize(Supplier)
. Per le funzioni con parametri, utilizzare CacheBuilder.build(CacheLoader)
con oggetti valore parametro come chiavi.
Questo esempio esegue la memoizzazione su tutti i metodi di un oggetto tramite un proxy. Ma la memoria tipica è una funzione al momento. Questa tecnica proxy sarebbe fastidiosa quando non si desidera memorizzare tutti i metodi di un oggetto. – lacroix1547