Wiem o tym jednym http://onjava.com/pub/a/onjava/2003/08/20/memoization.html, ale czy jest coś jeszcze?Jakie są różne techniki zapamiętywania w Javie?
Odpowiedz
memoization jest łatwe zwykły prosty typesafe Java.
Możesz zrobić to od podstaw, używając następujących klas wielokrotnego użytku.
Używam ich jako pamięci podręcznych, których długość życia jest wymagana na stronie internetowej.
Oczywiście użyj Guava MapMaker
, jeśli potrzebujesz strategii eksmisji lub więcej funkcji, takich jak synchronizacja.
Jeśli chcesz zapamiętać metodę z wieloma parametrami, po prostu umieść parametry na liście za pomocą obu technik i przekaż tę listę jako pojedynczy parametr.
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);
}
I to służy jak ten
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 nie jest jeszcze zatwierdzona dla naszego środowiska, oprogramowania finansowego ... – ranv01
Guava nie jest jeszcze zatwierdzona dla naszego środowiska. Oprogramowanie bankowe ... Ale to wystarczy. Ograniczę jednak rozmiar mapy, aby uniknąć wycieków pamięci. Nie dbam o eksmisje, ponieważ będzie to zachowane tylko podczas inwokacji jednej metody. – ranv01
Podobał mi się sposób, w jaki wysoko przetestowany kod nie został zatwierdzony, ale coś wklejone na SO to: :) –
przykład:
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 jest teraz przestarzały na rzecz CacheBuilder: https://code.google.com/p/guava-libraries/wiki/MapMakerMigration – dzieciou
@dzieciou W końcu zaktualizowałem kod do czegoś, co działa z najnowszym Guava (18.0 na obecny czas pisania). I tym razem jest testowany! –
Aby memoize funkcji bez parametrów użyć Guava na Suppliers.memoize(Supplier)
. W przypadku funkcji z parametrami należy użyć CacheBuilder.build(CacheLoader)
z obiektami wartości parametrów jako kluczami.
W tym przykładzie następuje zapamiętanie wszystkich metod obiektu za pośrednictwem serwera proxy. Ale typowa notyfikacja to jedna funkcja w tym czasie. Ta technika proxy byłaby denerwująca, gdybyś nie chciał zapamiętać wszystkich metod obiektu. – lacroix1547