実装は簡単ですが、すでに存在するものを再利用したいと思います。
解決したい問題は、さまざまなページ、ロールなどの構成を(XMLからキャッシュしたいので)読み込むことです。そのため、入力の組み合わせは非常に大きくなる可能性があります(ただし99%ではそうなりません)。この1%を処理するために、キャッシュに最大数のアイテムが必要です...
Apache commonsでorg.Apache.commons.collections.map.LRUMapを見つけたので、問題ないように見えますが、何か他のものもチェックしたいことを知っています。推奨事項はありますか?
LinkedHashMap (Java 1.4+)を使用できます:
// Create cache
final int MAX_ENTRIES = 100;
Map cache = new LinkedHashMap(MAX_ENTRIES+1, .75F, true) {
// This method is called just after a new entry has been added
public boolean removeEldestEntry(Map.Entry eldest) {
return size() > MAX_ENTRIES;
}
};
// Add to cache
Object key = "key";
cache.put(key, object);
// Get object
Object o = cache.get(key);
if (o == null && !cache.containsKey(key)) {
// Object not in cache. If null is not a possible value in the cache,
// the call to cache.contains(key) is not needed
}
// If the cache is to be used by multiple threads,
// the cache must be wrapped with code to synchronize the methods
cache = (Map)Collections.synchronizedMap(cache);
これは古い質問ですが、後世のために ConcurrentLinkedHashMap をリストしたいと思いました。これは LRUMap とは異なり、スレッドセーフです。使い方はとても簡単です:
ConcurrentMap<K, V> cache = new ConcurrentLinkedHashMap.Builder<K, V>()
.maximumWeightedCapacity(1000)
.build();
また、ドキュメントにはいくつかの優れた examples があり、LRUキャッシュをアイテム数ベースではなくサイズベースにする方法などがあります。
最適な数の要素をメモリに保持できる実装を次に示します。
ポイントは、MRUオブジェクトにLinkedHashMapとLRUオブジェクトにWeakHashMapの組み合わせを使用しているため、現在使用されているオブジェクトを追跡する必要がないことです。そのため、キャッシュ容量はMRUサイズに加えて、GCで保持できるものになります。オブジェクトがMRUから落下するたびに、GCがオブジェクトを保持している限り、オブジェクトはLRUに移動します。
public class Cache<K,V> {
final Map<K,V> MRUdata;
final Map<K,V> LRUdata;
public Cache(final int capacity)
{
LRUdata = new WeakHashMap<K, V>();
MRUdata = new LinkedHashMap<K, V>(capacity+1, 1.0f, true) {
protected boolean removeEldestEntry(Map.Entry<K,V> entry)
{
if (this.size() > capacity) {
LRUdata.put(entry.getKey(), entry.getValue());
return true;
}
return false;
};
};
}
public synchronized V tryGet(K key)
{
V value = MRUdata.get(key);
if (value!=null)
return value;
value = LRUdata.get(key);
if (value!=null) {
LRUdata.remove(key);
MRUdata.put(key, value);
}
return value;
}
public synchronized void set(K key, V value)
{
LRUdata.remove(key);
MRUdata.put(key, value);
}
}
私も同じ問題を抱えていて、良いライブラリが見つかりませんでした...自分で作成しました。
simplelrucacheは、TTLをサポートする、スレッドセーフで非常にシンプルな非分散LRUキャッシングを提供します。2つの実装を提供します。
あなたはそれを見つけることができます こちら 。
ここ は、Javaで非常にシンプルで使いやすいLRUキャッシュです。短くてシンプルですが、生産品質です。コードは説明されており(README.mdを参照)、いくつかの単体テストがあります。