2010-09-02 8 views

Odpowiedz

11

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); 
+0

Guava nie jest jeszcze zatwierdzona dla naszego środowiska, oprogramowania finansowego ... – ranv01

+0

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

+33

Podobał mi się sposób, w jaki wysoko przetestowany kod nie został zatwierdzony, ale coś wklejone na SO to: :) –

14

Tak. Użyj caches z Guava.

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)); 
     } 
    } 
} 
+7

MapMaker jest teraz przestarzały na rzecz CacheBuilder: https://code.google.com/p/guava-libraries/wiki/MapMakerMigration – dzieciou

+2

@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! –

16

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.

+0

Zobacz także https://github.com/google/guava/wiki/CachesExplained – Vadzim

+0

Przykład memoizacji: https://stackoverflow.com/questions/3636244/thread-safe-cache-of-one-object-in-java/ 3636791 # 3636791 – Vadzim

Powiązane problemy