2010-09-02 33 views

回答

11

記憶化也很容易用普通簡單類型安全的Java。

您可以從頭開始使用以下可重用類。

我使用這些作爲其生命週期是Web應用程序的請求的緩存。

如果您需要驅逐策略或更多功能(如同步),當然可以使用Guava MapMaker

如果您需要記憶具有多個參數的方法,只需將這兩個參數放入列表中,然後將該列表作爲單個參數傳遞。

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

,這是像這樣使用

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

番石榴尚未獲批准用於我們的環境,財務軟件...... – ranv01 2010-09-08 01:08:41

+0

番石榴尚未獲準用於我們的環境。銀行業軟件......但這會做。我會限制地圖的大小,以避免內存泄漏。我不在乎驅逐,因爲這隻會在調用一種方法時被保留下來。 – ranv01 2010-09-08 02:31:44

+33

我喜歡經過高度測試的代碼未被批准的方式,但粘貼在SO上的東西是:) – 2014-05-19 06:39:33

14

是的。從Guava使用caches

實施例:

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現在已被棄用,以支持CacheBuilder:https://code.google.com/p/guava-libraries/wiki/MapMakerMigration – dzieciou 2013-11-08 19:55:20

+2

@dzieciou我終於更新了代碼,使其與最新的Guava(18.0當前寫作時間)。這一次,它已經過測試! – 2015-03-22 05:35:01

16

爲了memoize的功能,而無需參數,使用番石榴的Suppliers.memoize(Supplier)。對於帶參數的函數,使用CacheBuilder.build(CacheLoader)和參數值對象作爲鍵。

+0

另請參閱https://github.com/google/guava/wiki/CachesExplained – Vadzim 2017-06-26 10:26:02

+0

備忘錄示例:https://stackoverflow.com/questions/3636244/thread-safe-cache-of-one-object-in-java/ 3636791#3636791 – Vadzim 2017-06-26 10:38:06