首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LinkedHashMap作为LRU缓存

LinkedHashMap作为LRU缓存
EN

Code Review用户
提问于 2011-06-27 02:50:54
回答 3查看 15.5K关注 0票数 11

我有一个使用LinkedHashMap的LRU缓存的简单实现。

  • 我希望它尽可能通用。
  • 这不是用于生产,只是实践,所以我不在乎它是否完全健壮,因为它是正确的。然而,我将欢迎任何评论,尤其是那些可能通过简单的更改使其更好的评论:)
  • 还有其他方法吗?
代码语言:javascript
复制
class LRUCache<E> {

    @SuppressWarnings("unchecked")
    LRUCache(int size)
    {
        fCacheSize = size;

        // If the cache is to be used by multiple threads,
        // the hashMap must be wrapped with code to synchronize 
        fCacheMap = Collections.synchronizedMap
        (
            //true = use access order instead of insertion order
            new LinkedHashMap<Object,E>(fCacheSize, .75F, true)
            {                                
                @Override
                public boolean removeEldestEntry(Map.Entry eldest)  
                {
                    //when to remove the eldest entry
                    return size() > 99 ;   //size exceeded the max allowed
                }
            }
        );
    }

    public void put(Object key, E elem)
    {
        fCacheMap.put(key, elem);
    }

    public E get(Object key)
    {
        return fCacheMap.get(key);
    }

    private Map<Object,E> fCacheMap;
    private int fCacheSize;
}
EN

回答 3

Code Review用户

发布于 2012-01-03 04:12:56

首先,正确使用泛型。

其次,如果您需要缓存大小,那么为什么要跟踪它呢?我会认为那是某种错误。

第三,如果您真的想惹恼大多数真正专业的java开发人员和课程指导人员(也就是说,那些编写Java代码的人就像用C#、C++或Pascal编程一样),请在类名和变量名前加上前缀。如果你不想这样做,不要这样做。

第四,我个人更喜欢自己来处理同步。这样,如果类被扩展为包含在映射中执行两个或多个操作的某个方法,我将不会破坏它。我添加了atomicGetAndSet方法来显示这一点。如果我依赖于Collections.synchronizedMap提供的同步,而不是我自己的同步,那么atomicGetAndSet方法将不是原子的,如果同时使用LRUCache实例,它就会中断。

考虑到这一点,您的代码变成如下:

代码语言:javascript
复制
public class LRUCache<K, V> {

    private final Map<K, V> cacheMap;

    public LRUCache(final int cacheSize) {

        // true = use access order instead of insertion order.
        this.cacheMap = new LinkedHashMap<K, V>(cacheSize, 0.75f, true) {                                
            @Override
            protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
                // When to remove the eldest entry.
                return size() > cacheSize; // Size exceeded the max allowed.
            }
        };
    }

    public synchronized void put(K key, V elem) {
        cacheMap.put(key, elem);
    }

    public synchronized V get(K key) {
        return cacheMap.get(key);
    }

    public synchronized V atomicGetAndSet(K key, V elem) {
        V result = get(key);
        put(key, elem);
        return result;
    }
}
票数 10
EN

Code Review用户

发布于 2014-08-26 08:31:39

来自LinkedHashMap的javadoc的说明:

注意,如果将键重新插入到映射中,则插入顺序不会受到影响。

因此,这将不是一个LRU地图,除非您确保所有的键是唯一的。

然而,在文件中还有:

提供了一个特殊的构造函数来创建一个链接的散列映射,其迭代顺序是最近一次访问其条目的顺序,从最近访问到最近访问(访问顺序)。这种地图非常适合于建立LRU缓存。

票数 3
EN

Code Review用户

发布于 2015-01-20 14:23:53

通过使用LinkedHashMap在生产代码中实现LRU缓存,我想说:为什么不继续实现完整的Map接口呢?在某种程度上,您可能会意识到您需要一个size()方法和一个entrySet()方法,可能还需要一些类似于Map的方法,所以最好通过遍历所有其他公共Map方法,使LRUCache成为包含的fCacheMap的外观。这就打开了一个实用程序类的整个世界,如果需要的话,这些类可以用于检查或操作Maps。

就像这样:

代码语言:javascript
复制
public class LRUCache<E> implements Map<Object, E> {
    // ...

    public int size()
    {
        return fCacheMap.size(key);
    }

    // etc...
}

当然,您可以决定Map接口的一个子集是足够的,也许可以使用类似于Collection的东西。这完全取决于您如何设想如何使用您的LRUCache

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/3138

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档