使用LinkedHashMap实现Cache的方法与原理
基于LinkedHashMap的特性,可以实现一个简单的基于LRU算法的缓存功能。
首先大致介绍一下LinkedHashMap的特点。
通过LinkedHashMap的签名我们可以看出 LinkedHashMap是HashMap的一个子类,它根据自身的特点修改了某些某类的方法
在这里八卦一下这个签名,我们可以看到LinkedHashMap继承了HashMap并实现了Map接口。
我们再来看一下HashMap的签名,HashMap继承了AbstractMap 并实现了Map接口,
我们再来看一下AbstractMap的签名
AbstractMap本身也实现了Map接口
但为什么HashMap和LinkedHashMap还要实现这个接口呢
在stackoverflow.网站找到了一个类似的帖子,只不过帖子问的是有关于WeakHashMap这个类的,但其道理是一样的
回复如下
大概意思是说只是为了生成javadoc会比较良好,其实在语法上是不需要的。
设计原理
LinkedHashMap我们都知道是基于双向链表的,如下图
但LinkedHashMap代源码中我们可以看出,他不仅是一个双向链表,而且是一个环型的双向链表
我们在源码可以看到LinkedHashMap的init方法覆盖了父类的方法
然而在HashMap类中init方法仅仅是一个空实现,为子类提供了一个勾子的作用
访问顺序
LinkedHashMap提供了两种Key的顺序
<!--[if !supportLists]-->l <!--[endif]-->访问顺序
<!--[if !supportLists]-->l <!--[endif]-->插入顺序
LinkedHashMap默认是插入顺序,这点我们在它的构造函数中可以看到
accessOrder就是访问顺序的意思,默认为false,即使用插入顺序
使用访问顺序的好处是,当我们使用get方法访问元素的时候,在访问过后,LinkedHashMap会将get的元素移到链表的尾部,这样链表的第一个元素总是最早被放入到链表中并且没有被访问过的元素,正好符合我们的LRU原则。
通过源码我们可以看到
LinkedHashMap并没有重写父类的put方法,
但是LinkedHashMap重新了父类put方法中的子方法addEntry方法
在addEntry方法中,我们看到了有一段代码,是否删除最老的一个元素。
按此推理,我们在实现缓存功能的时候,就需要重写removeEldestEntry方法,在添加元素的时候判断是否超过了缓存定义的容量。
按此方法,我在本地实现了一个简单的cache功能,代码如下
就这么简单。
测试代码如下:
1. 元素大小小于缓存容量
运行结果
2. 元素大小大于缓存容量
运行结果
3. 元素大小大于缓存容量,在缓存容量满之前对缓存数据进行访问
运行结果
相关推荐
在实际项目中,还可以考虑使用第三方库如Google的Guava库,它提供了高效且功能丰富的Cache实现,支持LRU和其他高级特性。然而,了解基本实现原理对于优化和定制自己的缓存解决方案至关重要。 总结,通过Java实现...
Java 实现 LRU 缓存有多种方法,本文将介绍使用 LinkedHashMap 实现 LRU 缓存的方法。 LRU 缓存原理 LRU 缓存的原理很简单,就是缓存一定量的数据,当超过设定的阈值时就把一些过期的数据删除掉。例如,我们缓存 ...
在Java中,可以使用`LinkedHashMap`实现LRU,因为它的插入和删除操作具有O(1)的时间复杂度,并能按照访问顺序自动排序。 现在让我们看看Java中如何实现这些算法: 对于FIFO,可以创建一个`LinkedList`存储缓存中的...
下面我们将详细探讨LRUCache的原理和如何使用`LinkedHashMap`来实现。 首先,理解LRU策略的关键在于数据的访问顺序。每次访问的数据会被移到链表的尾部,如果新的访问请求导致缓存溢出,那么链表头部的数据(即最久...
特别探讨分布式缓存的三大经典算法(LRU, LFU, FIFO),并给出具体实现案例——使用LinkedHashMap实现LRU缓存。接着,文章详细阐述常见的分布式缓存问题,如缓存穿透、雪崩和击穿,并提供详细的解决方案和技术手段。...
在Java中,可以使用LinkedHashMap实现LRU策略,因为该类维护了元素的插入顺序或者访问顺序。 并发访问控制是高速缓存实现中的另一大挑战。在Java中,可以使用synchronized关键字或者java.util.concurrent包中的工具...
LRUCache是一种常见的缓存策略,全称为Least Recently Used Cache,即最近最少使用缓存。它的核心理念是:当缓存满时,优先淘汰最近最少使用的数据。LRUCache广泛应用于计算机系统中,例如Android系统中,用于提高...
- 通过使用`LinkedHashMap`代替自定义的双向链表和`HashMap`组合,可以直接利用其内置的LRU行为,简化实现并提高效率。 7. **测试与调试**: 缓存实现完成后,通常会通过单元测试确保所有操作的正确性,例如测试...
本文将深入探讨LruCache的工作原理、使用方法以及如何在实际项目中进行有效利用。 LruCache全称为“Least Recently Used Cache”,即最近最少使用缓存策略。它是一种常用的缓存淘汰算法,当缓存空间满时,会优先...
在Java中,可以使用`LinkedHashMap`来实现LRU算法。`LinkedHashMap`兼具哈希表的高效查找和双向链表的顺序访问功能,适合用来记录数据的访问顺序。 1. **初始化LRU Cache**:创建一个`LinkedHashMap`实例,设置其...
LRUCache(Least Recently Used Cache,最近最少使用缓存)是一种常用的内存缓存策略,它通过维护一个固定大小的缓存,并按照数据的最近使用情况来决定哪些数据应该被保留,哪些数据可以被移除。 #### 二、LRUCache...
2. **实现类**:`SimpleCache`可能是实现`Cache`接口的具体类,它可能使用了Java集合框架中的数据结构,如HashMap或LinkedHashMap来存储缓存项,并且可能实现了缓存过期策略,比如基于时间的过期或者基于LRU(Least ...
二是关于LRU(Least Recently Used,最近最少使用)缓存策略的基本原理及其实现方式。 ### 1. 链表反转 链表反转是数据结构与算法中的一个经典问题。该问题的核心在于如何通过改变链表节点之间的指向关系,从而...
在Java中实现LRU缓存,我们可以借助一些内置工具或第三方库,如Java 8的`ConcurrentHashMap`结合`LinkedHashMap`,或者Google的Guava库中的`Cache`类。这篇博客文章可能讨论了如何使用这些工具来构建一个LRU缓存系统...
3. **容量管理**:可以使用LinkedHashMap实现LRU(最近最少使用)策略,当添加新元素导致缓存满时,删除最久未使用的项。 4. **过期策略**:可以为每个缓存项设置一个时间戳,每次`get`或`put`时更新,过期检查可以...
3. **性能优化**:在实际应用中,可以考虑使用Java 8的`LinkedHashMap`,它已经内置了LRU策略,无需自定义实现。 **应用场景** LRU缓存广泛应用于数据库查询、网页浏览历史记录、操作系统页替换策略等场景,以减少...
原理 之前分析过Lru算法的实现方式:HashMap+双向链表,参考链接: 这里主要介绍Android SDK中LruCache缓存算法的实现. 构造函数 LruCache只有一个构造函数,并且有一个必传参数: public LruCache(int maxSize) { if ...
在Java中,LRU算法常用于缓存设计,比如`HashMap`或`LinkedHashMap`的实现。 **LRU算法原理** LRU算法的核心思想是:如果一个数据最近被访问过,那么它在未来的访问概率会更高。因此,当缓存满时,应该优先移除最近...
1. LruCache:基于LinkedHashMap实现,它通过维护一个双向链表和哈希表,以最近最少使用的顺序淘汰元素。当达到预设的内存大小限制时,会自动删除最不常使用的项。 2. SoftReference和WeakReference:另一种策略是...