`
beyondyuefei
  • 浏览: 13087 次
  • 性别: Icon_minigender_1
  • 来自: 福州
文章分类
社区版块
存档分类
最新评论

轻松扩展LinkedHashMap类实现LRU算法

 
阅读更多
    今天偶然看到某框架源码自带的简单缓存策略算法LRU的实现,不想就几行代码即实现,原来只是简单的扩展了 jdk自带的LinkedHashMap类,如此简单,故分享之。

     具体关于
LinkedHashMap 的描述 不懂的自己去看 jdk api 文档,这里只说说怎么实现,翻开LinkedHashMap 源码 我们可以看到一段描述:
/**
* Returns <tt>true</tt> if this map should remove its eldest entry.
* This method is invoked by <tt>put</tt> and <tt>putAll</tt> after
* inserting a new entry into the map. It provides the implementor
* with the opportunity to remove the eldest entry each time a new one
* is added. This is useful if the map represents a cache: it allows
* the map to reduce memory consumption by deleting stale entries.
*
* <p>Sample use: this override will allow the map to grow up to 100
* entries and then delete the eldest entry each time a new entry is
* added, maintaining a steady state of 100 entries.
* <pre>
* private static final int MAX_ENTRIES = 100;
*
* protected boolean removeEldestEntry(Map.Entry eldest) {
* return size() > MAX_ENTRIES;
* }
**/

protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
 

    意思就是说 在 put() 或者 putAll() 操作后会调用此方法判断 是否需要 清除最旧的那个元素,默认是返回 false,即不做操作。注意此 方法 是 protected ,即用于子类覆盖的,可以说这是 jdk的开发者特意留下来为我们实现LRU提供的,注释也说了,我们可以简单的覆盖此方法实现 LRU ,如:
public class LruCache implements Cache {

private final Map<Object, Object> store;
private int initialCapacity = 16;
private float loadFactor = 0.75f;
private boolean accessOrder = true;

public LruCache(URL url) {
final int max = 1000; // 缓存中最多1000个元素
this.store = new LinkedHashMap<Object, Object>(initialCapacity,loadFactor,accessOrder){
private static final long serialVersionUID = -3834209229668463829L;
@Override
protected boolean removeEldestEntry(Entry<Object, Object> eldest) {
return size() > max;
}
};
}
}
 

    这样当 stroe 中的元素超过 max=1000个时,将从 map 中删除 最旧的那个元素,即实现了 LRU。
需要注意的是,
LinkedHashMap 并未覆盖 父类 HashMap中的 put() 和 putAll() ,而是覆盖了 会被 put() 调用的addEntry() 方法,我们来看下LinkedHashMap中的addEntry() :

void addEntry(int hash, K key, V value, int bucketIndex) {
createEntry(hash, key, value, bucketIndex);

// Remove eldest entry if instructed, else grow capacity if appropriate
Entry<K,V> eldest = header.after;
if (removeEldestEntry(eldest)) {
removeEntryForKey(eldest.key);
}else {
if (size >= threshold)
resize(2 * table.length);
}
}
 

    看到了吧,如果返回为 true,则会删除最旧的那个元素,so simple
 
   ps: 如果在多线程环境下使用,由于其父类 HashMap不支持同步,所以需要重写 get put 方法,无非就是加个同步:
 
    
 public void put(Object key, Object value) {
        synchronized (store) {
            store.put(key, value);
        }
    }

    public Object get(Object key) {
        synchronized (store) {
            return store.get(key);
        }
    }
 
 
   
分享到:
评论

相关推荐

    LRU算法四种实现方式介绍.docx

    LRU-K 的主要目的是为了解决 LRU 算法“缓存污染”的问题,其核心思想是将“最近使用过 1 次”的判断标准扩展为“最近使用过 K 次”。相比 LRU,LRU-K 需要多维护一个队列,用于记录所有缓存数据被访问的历史。 LRU...

    实现了LRU算法的缓存

    LRU(Least Recently Used)算法是一种常用的页面替换策略,用于管理有限的缓存资源。...为了进一步学习和应用,你可以尝试阅读源码,理解每个类和方法的作用,甚至修改和扩展这个实现以满足特定需求。

    LRU.rar_LRU_LRU java_lru.java

    根据文件名,`LRU.java`应该是包含LRU算法实现的Java源代码文件。这个文件可能定义了一个名为`LRU`的类,其中包含了构造函数、添加元素的方法、以及可能的获取和移除元素的方法。具体的实现细节,包括如何管理和更新...

    Java和Android的LRU缓存及实现原理

    二、Java中的LRU算法与LinkedHashMap 1. `HashMap`基础 `LinkedHashMap`是在`HashMap`基础上扩展的。`HashMap`采用数组+链表的数据结构,其中每个元素是一个`Entry, V&gt;`对象。`Entry`包含键值对的key、value以及指向...

    Redis面试专题及答案(下).pdf

    在Java代码中,可以使用LinkedHashMap来实现LRU缓存。 总结一下,Redis不仅提供了丰富的数据结构和持久化机制,还具有处理高并发和设计分布式锁的能力。对于Java开发者来说,掌握Redis的基本原理和使用方法是十分...

    Redis面试专题.docx

    #### LRU算法实现 LRU (Least Recently Used) 算法是一种常用的缓存淘汰策略,用于管理有限缓存空间中的数据项。 ```java import java.util.LinkedHashMap; import java.util.Map; public class LRUCache, V&gt; ...

    Redis面试专题.pdf

    ### Redis的过期策略与LRU算法 1. **过期策略**: - **定时过期**:每个键关联一个定时器,定时检查键是否过期。 - **惰性过期**:仅在使用键时检查其是否过期。 - **定期过期**:结合上述两种策略,定期检查并...

    java超有用的面试题目

    - **Classloader**:包括启动类加载器、扩展类加载器、应用类加载器等,采用双亲委派机制。 #### Java内存模型与并发应用 - **指令重排序**:为了优化性能,编译器和处理器可能会重新排列指令执行顺序。 - **内存...

    Backend-system-key-algorithms:后端系统算法

    在后端系统开发中,算法扮演着至关重要的角色,它们是构建高效、稳定且可扩展的系统的基石。这里我们将深入探讨“Backend-system-key-algorithms”这个主题,特别关注与Java相关的算法。 首先,我们来理解后端系统...

    字节跳动大数据面试题汇总(精华版).pdf

    - QJM基于Paxos算法实现高可用Namenode日志服务。 - 字节跳动选择BookKeeper替代QJM,可能是考虑到BookKeeper的扩展性和性能更优秀。 6. **字节跳动技术改进** - 在HDFS方面,可能涉及元数据管理、数据一致性...

    基于Java的实例源码-Java缓存工具 SimpleCache.zip

    2. **实现类**:`SimpleCache`可能是实现`Cache`接口的具体类,它可能使用了Java集合框架中的数据结构,如HashMap或LinkedHashMap来存储缓存项,并且可能实现了缓存过期策略,比如基于时间的过期或者基于LRU(Least ...

    Java技术专家笔试题.pdf

    - 当缓存达到容量限制时,需要有策略决定哪些缓存项被移除,例如LRU(最近最少使用)算法。 以上各个知识点覆盖了从数据结构设计到系统架构的多个方面,对于Java高级开发人员来说,这些是面试中常见的技术难题。...

    J2EE开发全程实录PDF J2EE开发全程实录PDF

    - **Java中的Map接口**:提供了键值对的存储和检索功能,常见的实现类有`HashMap`、`TreeMap`、`LinkedHashMap`等。 - **HashMap**: - **应用举例**:展示如何使用`HashMap`存储和检索数据。 - **Map与HashCode*...

    java程序员面试大纲错过了金三银四你还要错过2018吗.docx

    8. **Java LinkedHashMap的应用**:`LinkedHashMap`保持了插入顺序,常用于实现LRU缓存等场景。 9. **cloneable接口实现原理**:实现了`Cloneable`接口的对象可以通过`clone()`方法进行浅复制,深复制需要自定义...

    Data-Structures:在不同数据结构上实践的一些问题

    LinkedHashMap保持了元素的插入顺序,也可设置为访问顺序,这对于实现LRU缓存策略很有用。 实践中,了解每种数据结构的特性和适用场景至关重要。结合实际需求选择合适的数据结构,可以大大提高代码效率。此外,还要...

Global site tag (gtag.js) - Google Analytics