2010-09-02 5 views

Antwort

11

memoization ist auch einfach, mit einfachen einfachen typsichere Java.

Sie können es mit den folgenden wiederverwendbaren Klassen von Grund auf neu erstellen.

Ich verwende diese als Caches, deren Lebensdauer die Anfrage auf einer Webapp sind.

Natürlich verwenden Sie die Guava MapMaker, wenn Sie eine Räumungsstrategie oder mehr Funktionen wie Synchronisation benötigen.

Wenn Sie eine Methode mit vielen Parametern memoisieren müssen, fügen Sie die Parameter in eine Liste mit beiden Techniken ein und übergeben diese Liste als einzigen Parameter.

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

Und das verwendet wird, wie diese

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 ist noch nicht für unsere Umwelt zugelassen, finanzielle Software ... – ranv01

+0

Guava ist noch nicht für unsere Umwelt zugelassen. Banking-Software ... Aber das wird es tun. Ich werde die Größe der Karte jedoch begrenzen, um Speicherlecks zu vermeiden. Mir sind Räumungen egal, da dies nur während des Aufrufs einer Methode erhalten bleibt. – ranv01

+33

Ich mag die Art, wie hoch getesteter Code nicht genehmigt ist, aber etwas auf SO eingefügt ist :) –

14

Ja. Verwenden Sie caches von Guava.

Beispiel:

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 ist jetzt zugunsten von CacheBuilder veraltet: https://code.google.com/p/guava-libraries/wiki/MapMakerMigration – dzieciou

+2

@dzieciou Ich habe den Code endlich auf etwas aktualisiert, das mit der neuesten Guava funktioniert (18.0 at aktuelle Schreibzeit). Und dieses Mal ist es getestet! –

16

Um Funktionen ohne Parameter memoize verwenden Guava des Suppliers.memoize(Supplier). Verwenden Sie für Funktionen mit Parametern CacheBuilder.build(CacheLoader) mit Parameterwertobjekten als Schlüssel.

+0

Siehe auch https://github.com/google/guava/wiki/CachesErklärt – Vadzim

+0

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

Verwandte Themen