74

実装は簡単ですが、既存のものを再利用したいと思います。

私が解決したい問題は、さまざまなページ、ロールなどの構成を(XMLからキャッシュしたいので)ロードすることです。そのため、入力の組み合わせはかなり大きくなる可能性があります(ただし、99%では大きくなりません)。この1%を処理するために、キャッシュに最大数のアイテムを入れたいです...

私がApacheCommonsでorg.apache.commons.collections.map.LRUMapを見つけたことがわかるまで、それは問題ないように見えますが、他の何かもチェックしたいと思います。何かお勧めはありますか?

4

5 に答える 5

119

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);
于 2008-10-22T08:33:08.737 に答える
33

これは古い質問ですが、後世のためにLRUMapとは異なり、スレッドセーフなConcurrentLinkedHashMapをリストしたいと思いました。使い方はとても簡単です:

ConcurrentMap<K, V> cache = new ConcurrentLinkedHashMap.Builder<K, V>()
    .maximumWeightedCapacity(1000)
    .build();

ドキュメントには、アイテム数ベースではなくサイズベースの LRU キャッシュを作成する方法など、いくつかの良い例があります。

于 2011-09-28T13:41:04.600 に答える
14

これは、最適な数の要素をメモリに保持できるようにする私の実装です。

要点は、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);
}
}
于 2012-07-31T00:21:00.870 に答える
1

これは、Java での非常にシンプルで使いやすい LRU キャッシュです。短くてシンプルですが、製品品質です。コードは説明されており (README.md を参照)、いくつかの単体テストが含まれています。

于 2012-02-19T09:40:42.003 に答える
1

私も同じ問題を抱えていて、良いライブラリが見つからなかったので、自分で作成しました。

simplelrucache は、TTL をサポートする、スレッドセーフで非常に単純な非分散型 LRU キャッシングを提供します。2 つの実装を提供します。

  • ConcurrentLinkedHashMap に基づく同時実行
  • LinkedHashMap に基づいて同期

ここで見つけることができます。

于 2011-12-21T12:09:35.633 に答える