链表保存键值,由于没有权值策略,简单的将当前访问过的节点放到链表头部,则存在如下问题:
在周期性访问中,某个周期中存在一部分数据仅仅只访问了一次,则最终导致缓存中的数据都是无效的数据,而将频繁访问的数据排除了。在实际应用中,这种简单策略不适用。
TestCode
public class LRUCacheTest {
/**
* @param args
*/
public static void main(String[] args) {
LRUCache cache = new LRUCache(10);
for(int i=0;i<100;i++)
{
cache.put(i+"", "hello_"+i);
// System.out.println(cache.size());
}
cache.printFrontTrace();
System.out.println();
cache.printBackwardTrace();
System.out.println("\n-------------");
cache.remove("90");
cache.printFrontTrace();
System.out.println();
cache.printBackwardTrace();
System.out.println("\n"+cache.get("92"));
System.out.println("\n-------------");
cache.printFrontTrace();
System.out.println("\n"+cache.get("91"));//get tail
System.out.println("\n-------------");
cache.printFrontTrace();
System.out.println("\n"+cache.get("91"));//get head
System.out.println("\n-------------");
cache.printFrontTrace();
cache.remove("91");//remove head
System.out.println("\n-------------");
cache.printFrontTrace();
//
cache.remove("93");//remove tail
System.out.println("\n-------------");
cache.printFrontTrace();
for(int i=0;i<100;i++)//remove all
{
cache.remove(i+"");
// System.out.println(cache.size());
}
System.out.println("\n-------------now size = "+cache.size());
cache.printFrontTrace();
}
}
LRU缓存类,采用双向链表保存键,Hash保存值
package org.jf.alg.lru;
import java.util.HashMap;
import java.util.Map;
/**
*
* LRU 简单实现
* 双向链表+HashMap
* @author chenjf
*
*/
public class LRUCache
{
private KeyNode head;//key值的链表头 (包含数据)
private KeyNode tail;//key值的链表尾 (包含数据)
private int capacity;
private int size;
private Map<Object,CacheObject> map = new HashMap<Object,CacheObject>();
public LRUCache(int capacity)
{
this.capacity=capacity;
}
public void put(Object key,Object value)
{
if(value==null)
return;
Object obj = this.get(key);
if(obj!=null)
return;
KeyNode node = new KeyNode(key);
CacheObject cache_obj = new CacheObject(node,value);
map.put(key, cache_obj);
if(head==null)
{
head = node;
tail = node;
size++;
}else
{
head.previous = node;
node.next = head;
head = node;
size++;
if(size>capacity)
{
remove(tail.key);
}
}
}
public Object remove(Object key)
{
Object data = null;
Object obj = map.remove(key);
if(obj!=null)
{
CacheObject cache_obj = (CacheObject)obj;
KeyNode node = cache_obj.keyNode;
if(size==1)
{
head = null;
tail = null;
}else
{
if(node.equals(head))
{
if(head.next!=null)//not tail
head.next.previous = null;
head = head.next;
node.next = null;
}else if(node.equals(tail))
{
tail = node.previous;
if(tail!=null)
{
tail.next = null;
}
node.previous = null;
}else// not head and tail
{
node.previous.next=node.next;
node.next.previous=node.previous;
node.previous=null;
node.next=null;
}
}
data = cache_obj.data;
size--;
}
return data;
}
public Object get(Object key)
{
Object data = null;
Object obj = map.get(key);
if(obj!=null)
{
CacheObject cache_obj = (CacheObject)obj;
KeyNode node = cache_obj.keyNode;
if(!node.equals(head))//if node is head, nothing to do
{
node.previous.next = node.next;
if(node.next!=null)
node.next.previous = node.previous;
else// node is tail
tail = node.previous;
node.next = head;
head.previous = node;
node.previous = null;
head = node;
}
data = cache_obj.data;
}
return data;
}
public void clear()
{
head = null;
tail = null;
size = 0;
map.clear();
}
public int size()
{
return this.size;
}
public int getCapacity()
{
return this.capacity;
}
/**
*
* for debug
*/
public void printFrontTrace()
{
//print front from head to tail
if(head!=null)
{
KeyNode node = head;
while(node!=null)
{
System.out.print("-->"+node.key+"["+map.get(node.key).data+"]");
node=node.next;
}
}
}
public void printBackwardTrace()
{
if(tail!=null)
{
KeyNode node = tail;
while(node!=null)
{
System.out.print("<--"+node.key+"["+map.get(node.key).data+"]");
node=node.previous;
}
}
}
/****************************inner class from object store**************************************/
class KeyNode
{
KeyNode previous;
KeyNode next;
Object key;
public KeyNode(Object key)
{
this.key = key;
}
}
class CacheObject
{
public CacheObject(KeyNode node,Object data)
{
keyNode = node;
this.data = data;
}
KeyNode keyNode;
Object data;
}
}
分享到:
相关推荐
在Go语言中,有许多库可以帮助开发者实现LRU缓存,其中"Go-一个简单高效用于go的LRU缓存包"就是一个这样的工具。这个包为Go程序员提供了简单、高效的LRU缓存接口,便于在应用程序中管理和优化数据存储。 在Go语言中...
这里的LRUCache类维护了一个双向链表和一个哈希表,用于实现LRU算法。具体实现细节如下: - get方法:首先在哈希表中查找对应的键值对,如果不存在,则返回-1;如果存在,则将对应的节点从双向链表中删除,并将其...
标题中的"quicklru简单的最近最少使用LRU缓存"指的是一种轻量级的LRU实现,旨在提供高效且易于使用的缓存解决方案。它可能是一个小型库,专为JavaScript环境设计,用于存储和检索数据,同时保持较低的内存占用。 ...
Java实现简单LRU缓存机制的方法 Java实现简单LRU缓存机制的方法是指通过Java语言实现的一种缓存机制,该机制可以根据最近最少使用的原则淘汰缓存中的数据。缓存机制的实现主要是通过哈希表和双向链表来实现的。 ...
使用 LinkedHashMap 实现 LRU 缓存是最简单的方法,因为 LinkedHashMap 自身已经实现了顺序存储,默认情况下是按照元素的添加顺序存储,也可以启用按照访问顺序存储,即最近读取的数据放在最前面,最早读取的数据...
今天我们将讨论如何使用链表来实现LRU缓存淘汰算法。 首先,让我们来讨论缓存的概念。缓存是一种提高数据读取性能的技术,它广泛应用于CPU缓存、数据库缓存、浏览器缓存等领域。当缓存被用满时,需要淘汰一些数据以...
LRU 算法的实现简单,但命中时需要遍历链表,找到命中的数据块索引,然后需要将数据移到头部。 4. LRU-K 算法 LRU-K 算法是为了解决 LRU 算法“缓存污染”的问题,其核心思想是将“最近使用过 1 次”的判断标准...
**Swift-SPTPersistentCache:一个高效且灵活的LRU缓存管理框架** 在iOS和macOS应用开发中,缓存管理是性能优化的关键部分。它能够帮助减少网络请求,提高用户体验,尤其是在处理大量数据或者频繁访问同一资源时。`...
在缓存或者数据库管理系统中,LRU算法被广泛应用,因为它的实现简单且效果良好。 LRU算法的核心思想是:当内存满时,最近最少使用的数据会被优先淘汰。也就是说,如果一个数据最近被访问过,那么它在未来被访问的...
在Python中,可以使用`functools.lru_cache`装饰器实现LRU缓存,或者自定义双向链表和哈希表实现。 在实际应用中,LRU缓存策略常用于数据库的查询缓存、Web服务器的动态页面缓存、编程语言解释器的符号表等场景。...
以下是简单的LRU缓存实现: ```java import java.util.HashMap; import java.util.LinkedList; import java.util.Map; public class LRUCache, V> implements LRUCache, V> { private int capacity; private Map...
链表(上):如何实现 LRU 缓存淘汰算法? 链表是一种基础的数据结构,学习链表有什么用呢?为了回答这个问题,我们来讨论一个经典的链表应用场景,那就是 LRU 缓存淘汰算法。缓存是一种提高数据读取性能的技术,在...
以下是一个简单的LRU缓存实现的Java代码框架: ```java class LRUCache, V> { private int capacity; private HashMap, Node> map; private DoublyLinkedList<Node> list; public LRUCache(int capacity) { ...
描述:这个项目有点像实验,涉及 3 种不同的 LRU 缓存实现。 一个使用最小堆(通常用于优先级队列)而不是 OrderedDict,第二个使用集合包中的内置 OrderedDict,最后一个使用我自己的 OrderedDict 的简单实现。 ...
下面详细介绍如何使用 Java 实现一个简单的 LRU 缓存机制。 ##### 1. 定义双向链表节点类 `Node` ```java class Node { int key; int value; Node prev; Node next; public Node(int key, int value) { ...
PHP LRU缓存实现介绍WTF 是 LRU 缓存吗? LRU 代表最近最少使用。 它是一种缓存类型,通常具有固定容量并丢弃最旧的条目。 如果您需要控制缓存内存使用,这将特别有用。 如果您想了解有关 LRU Cache 的更多详细信息...
node-lru-native, 面向 node.js的高性能LRU缓存 node-lru-native这是 node.js 内存缓存的简单实现,支持 LRU ( least-recently-used ) 备份和 TTL expirations 。它是作为与( 精彩) node-lru-cache库的替代
例如,以下是一个简单的LRU缓存实现,使用`LinkedHashMap`的继承方式: ```java public class LRUCache2, V> extends LinkedHashMap, V> { private final int MAX_CACHE_SIZE; public LRUCache2(int cacheSize) ...
总之,`array-lru`是一个适用于JavaScript开发的高效数组型LRU缓存库,它的简单API和高性能特性使其成为优化小型缓存需求的理想选择。开发者可以根据具体项目需求,灵活地使用和定制这个库,提升应用程序的运行效率...
以下代码段展示了如何在Node.js中实现一个简单的LRU缓存: ```javascript function CacheLRU(capacity) { this.capacity = capacity || Number.MAX_VALUE; this.data = {}; // 存储缓存值 this.hash = {}; // ...