今天偶然看到某框架源码自带的简单缓存策略算法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-K 的主要目的是为了解决 LRU 算法“缓存污染”的问题,其核心思想是将“最近使用过 1 次”的判断标准扩展为“最近使用过 K 次”。相比 LRU,LRU-K 需要多维护一个队列,用于记录所有缓存数据被访问的历史。 LRU...
LRU(Least Recently Used)算法是一种常用的页面替换策略,用于管理有限的缓存资源。...为了进一步学习和应用,你可以尝试阅读源码,理解每个类和方法的作用,甚至修改和扩展这个实现以满足特定需求。
根据文件名,`LRU.java`应该是包含LRU算法实现的Java源代码文件。这个文件可能定义了一个名为`LRU`的类,其中包含了构造函数、添加元素的方法、以及可能的获取和移除元素的方法。具体的实现细节,包括如何管理和更新...
二、Java中的LRU算法与LinkedHashMap 1. `HashMap`基础 `LinkedHashMap`是在`HashMap`基础上扩展的。`HashMap`采用数组+链表的数据结构,其中每个元素是一个`Entry, V>`对象。`Entry`包含键值对的key、value以及指向...
在Java代码中,可以使用LinkedHashMap来实现LRU缓存。 总结一下,Redis不仅提供了丰富的数据结构和持久化机制,还具有处理高并发和设计分布式锁的能力。对于Java开发者来说,掌握Redis的基本原理和使用方法是十分...
#### LRU算法实现 LRU (Least Recently Used) 算法是一种常用的缓存淘汰策略,用于管理有限缓存空间中的数据项。 ```java import java.util.LinkedHashMap; import java.util.Map; public class LRUCache, V> ...
### Redis的过期策略与LRU算法 1. **过期策略**: - **定时过期**:每个键关联一个定时器,定时检查键是否过期。 - **惰性过期**:仅在使用键时检查其是否过期。 - **定期过期**:结合上述两种策略,定期检查并...
- **Classloader**:包括启动类加载器、扩展类加载器、应用类加载器等,采用双亲委派机制。 #### Java内存模型与并发应用 - **指令重排序**:为了优化性能,编译器和处理器可能会重新排列指令执行顺序。 - **内存...
在后端系统开发中,算法扮演着至关重要的角色,它们是构建高效、稳定且可扩展的系统的基石。这里我们将深入探讨“Backend-system-key-algorithms”这个主题,特别关注与Java相关的算法。 首先,我们来理解后端系统...
- QJM基于Paxos算法实现高可用Namenode日志服务。 - 字节跳动选择BookKeeper替代QJM,可能是考虑到BookKeeper的扩展性和性能更优秀。 6. **字节跳动技术改进** - 在HDFS方面,可能涉及元数据管理、数据一致性...
2. **实现类**:`SimpleCache`可能是实现`Cache`接口的具体类,它可能使用了Java集合框架中的数据结构,如HashMap或LinkedHashMap来存储缓存项,并且可能实现了缓存过期策略,比如基于时间的过期或者基于LRU(Least ...
- 当缓存达到容量限制时,需要有策略决定哪些缓存项被移除,例如LRU(最近最少使用)算法。 以上各个知识点覆盖了从数据结构设计到系统架构的多个方面,对于Java高级开发人员来说,这些是面试中常见的技术难题。...
- **Java中的Map接口**:提供了键值对的存储和检索功能,常见的实现类有`HashMap`、`TreeMap`、`LinkedHashMap`等。 - **HashMap**: - **应用举例**:展示如何使用`HashMap`存储和检索数据。 - **Map与HashCode*...
8. **Java LinkedHashMap的应用**:`LinkedHashMap`保持了插入顺序,常用于实现LRU缓存等场景。 9. **cloneable接口实现原理**:实现了`Cloneable`接口的对象可以通过`clone()`方法进行浅复制,深复制需要自定义...
LinkedHashMap保持了元素的插入顺序,也可设置为访问顺序,这对于实现LRU缓存策略很有用。 实践中,了解每种数据结构的特性和适用场景至关重要。结合实际需求选择合适的数据结构,可以大大提高代码效率。此外,还要...