java中易于使用的LRU缓存

java中易于使用的LRU缓存,java,caching,lru,Java,Caching,Lru,我知道实现起来很简单,但我想重用已经存在的东西 我想解决的问题是,我为不同的页面、角色等加载配置(从XML加载,所以我想缓存它们)。。。因此,投入的组合可以增长很多(但在99%的情况下不会)。要处理这1%,我希望缓存中有一些最大数量的项 直到我知道我在ApacheCommons中找到了org.apache.commons.collections.map.LRUMap,它看起来不错,但我还想检查一些其他东西。有什么建议吗?您可以使用(Java 1.4+): 这是一个老生常谈的问题,但对于子孙后代,

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

我想解决的问题是,我为不同的页面、角色等加载配置(从XML加载,所以我想缓存它们)。。。因此,投入的组合可以增长很多(但在99%的情况下不会)。要处理这1%,我希望缓存中有一些最大数量的项

直到我知道我在ApacheCommons中找到了org.apache.commons.collections.map.LRUMap,它看起来不错,但我还想检查一些其他东西。有什么建议吗?

您可以使用(Java 1.4+):


这是一个老生常谈的问题,但对于子孙后代,我想列出它,它是线程安全的,不像。使用非常简单:

ConcurrentMap<K, V> cache = new ConcurrentLinkedHashMap.Builder<K, V>()
    .maximumWeightedCapacity(1000)
    .build();
ConcurrentMap缓存=新建ConcurrentLinkedHashMap.Builder()
.最大加权容量(1000)
.build();

文档也有一些好处,比如如何使LRU缓存大小基于项目数而不是基于项目数。

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

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

  • 基于ConcurrentLinkedHashMap的并发
  • 基于LinkedHashMap的同步
您可以找到它。

是Java中非常简单且易于使用的LRU缓存。 虽然它是简短和简单的,但它是生产质量。
代码已经解释过了(请看README.md)并进行了一些单元测试。

下面是我的实现,它让我在内存中保留了最佳数量的元素

关键是,我不需要跟踪当前正在使用的对象,因为我使用的是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);
}
}
公共类缓存{
最终地图MRUdata;
最终地图LRUdata;
公共缓存(最终整数容量)
{
LRUdata=newweakhashmap();
MRUdata=新LinkedHashMap(容量+1,1.0f,真){
受保护的布尔RemoveedStentry(Map.Entry)
{
if(this.size()>容量){
LRUdata.put(entry.getKey(),entry.getValue());
返回true;
}
返回false;
};
};
}
公共同步V-tryGet(K键)
{
V值=MRUdata.get(键);
if(值!=null)
返回值;
value=LRUdata.get(键);
if(值!=null){
LRUdata.remove(键);
MRUdata.put(键、值);
}
返回值;
}
公共同步无效集(K键,V值)
{
LRUdata.remove(键);
MRUdata.put(键、值);
}
}

好的,所以我决定使用LRUMap。请注意,您的两个链接都指向同一个示例,我认为前者应该是LHM javadoc?我今天发现了LinkedHashMap的这一方面,它的简单程度令人惊讶。经验教训:了解您的API。清楚编写的示例(基于java.util.LinkedHashMap的LRU缓存类)运行时还提供了一个测试:负载系数真的应该是.75吗?就像你从来都不希望地图包含超过MAX_的条目一样。@Suporwski你是如何解决这个问题的?@Hunt我有来自Commons的LRUMap非常类似的问题也可以请你在Maven Central中发布你的库吗?版本1.0现在应该在Central:)是Java 8重写,这是而且提供了更多。这是一个很好的方法。所以LRU缓存只存储大小受限的MRU缓存中已经过期的内容。它就像一个软件二级缓存。美好的如果数据碰巧出现在LRUdata中,但在MRUdata中丢失,则可能会向应用程序日志发出有关增加缓存大小的有用警告/提示。
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);
}
}