74

我知道实现起来很简单,但我想重用已经存在的东西。

我要解决的问题是我为不同的页面、角色加载配置(来自 XML,所以我想缓存它们)......所以输入的组合可以增长很多(但 99% 不会)。为了处理这 1%,我想在缓存中有一些最大数量的项目......

直到知道我在 apache commons 中找到了 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

这是一个老问题,但为了后代,我想列出ConcurrentLinkedHashMap,它是线程安全的,不像LRUMap。用法很简单:

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

我也有同样的问题,我还没有找到任何好的库......所以我创建了自己的库。

simplelrucache 提供线程安全、非常简单、非分布式 LRU 缓存,支持 TTL。它提供了两种实现

  • 基于 ConcurrentLinkedHashMap 的并发
  • 基于LinkedHashMap同步

你可以在这里找到它。

于 2011-12-21T12:09:35.633 回答
1

是一个非常简单易用的 Java 中的 LRU 缓存。尽管它简短而简单,但它是生产质量。对代码进行了解释(查看 README.md)并进行了一些单元测试。

于 2012-02-19T09:40:42.003 回答