介绍
这篇文章主要讲解了Java实现一个基于LRU时间复杂度为O(1)的缓存的方法,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。
LRU:最近最少使用最近最少使用,当缓存容量不足时,先淘汰最近最少使用的数据。就像JVM垃圾回收一样,希望将存活的对象移动到内存的一端,然后清除其余空间。
缓存基本操作就是读,写,淘汰删除。
读操作时间复杂度为O(1)的那就是散列操作了,可以使用HashMap索引关键。
写操作时间复杂度为O(1),使用链表结构,在链表的一端插入节点,是可以完成O(1)操作,但是为了配合读,还要再次将节点放入HashMap中,把操作最优是O(1),最差是O (n)。
不少童鞋就有疑问了,写入时又使用地图进行了把操作,为何缓存不直接使用地图吗?没错,首先使用地图存储了节点数据就是采用空间换时间,但是淘汰删除不好处理,使用地图如何去记录最近最少使用(涉及到时间,频次问题)所以,使用链表可以将活跃节点移动到链表的一端,淘汰时直接从另一端进行删除。
公共类LruCache{/* *这里简单点直接初始化了*/私人int能力=2; 私人int大?0; DoubleListNode<私人HashMap 比;缓存=new HashMap<祝辞(能力); 私人DoubleListNode lruNode=new DoubleListNode (空,空,空,空); 私人DoubleListNode mruNode=new DoubleListNode (空,空,空,空); 公共V (K键){ DoubleListNode 目标=cache.get(关键); 如果目标==null) { 返回null; }/* *使用过就移动到右侧*/move2mru(目标); 返回target.value; } 公共空间把(K键,V值){ 如果(cache.containsKey(关键)){ DoubleListNode temp=cache.get(关键); temp.value=https://www.yisu.com/zixun/value;/* *使用过就移动到右侧*/move2mru(临时); 返回; }/* *容量满了清除左侧*/如果(大?=能力){ evict4lru (); } DoubleListNode newNode=new DoubleListNode <> (mruNode、零键,值); 如果(大?=0){ lruNode。下一个=newNode; } mruNode。下一个=newNode; mruNode=newNode; cache.put(关键,newNode); 大小+ +; } 私人空间move2mru (DoubleListNode newMru) { DoubleListNode pre=newMru.pre; 未来=newMru.next DoubleListNode ; 精准医疗下一个=下一个; newMru。pre=mruNode; mruNode。下一个=newMru; mruNode=newMru; } 私人空间evict4lru () { cache.remove (lruNode.next.key); lruNode。下一个=lruNode.next.next; 大小,; } 公共字符串toString () { StringBuffer某人=new StringBuffer (“lru ->”); DoubleListNode temp=lruNode; 而(临时!=null) { sb.append (temp.key) .append (“:”) .append (temp.value); sb.append (" -> "); temp=temp.next; } sb.append(“->系统”); 返回sb.toString (); } 公共静态void main (String [] args) { 缓存=new LruCache LruCache <字符串,字符串> <> (); cache.put (“1”,“1”); System.out.println(缓存); cache.get (" 1 "); cache.put (“2”,“2”); System.out.println(缓存); cache.put (“3”,“3”); System.out.println(缓存); cache.put (“4”,“4”); System.out.println(缓存); } } 类DoubleListNode { K键; V值; DoubleListNode 前; DoubleListNode 下; 公共DoubleListNode (K键,V值){ 这一点。键=键; 这一点。值=价值; } 公共DoubleListNode (DoubleListNode 之前,DoubleListNode 其次,K键,V值){ 这一点。pre=前; 这一点。下一个=下一个; 这一点。键=键; 这一点。值=价值; } }
这里使用链表,及HashMap完成了基于LRU的缓存,其中HashMap主要用来快速索引键,链表用来完成LRU机制。当然尚有许多不足,包括缓存移除删除缓存ttl、线程安全等。
看完上述内容,是不是对Java实现一个基于LRU时间复杂度为O(1)的缓存的方法有进一步的了解,如果还想学习更多内容,欢迎关注行业资讯频道。