8.16 lru缓存java版

lru详细介绍及简单代码实现:

http://blog.csdn.net/beiyetengqing/article/details/7855933

以下是本人的加强的lru缓存类,增加单例获取、缓存超时机制和修复一个clear()的bug

package com.george.xblog.utils;

import java.util.Hashtable;
import java.util.Map;

/**
 * Created by george.yang on 15/8/15.
 */
public class LruCache {

    private static final class Entry {
        public String key;// 键
        public Object value;// 值
        public Entry prev;// 前一节点
        public Entry next;// 后一节点
        public long validTime;//有效的最大时间
    }

    private static LruCache instance;
    public static synchronized LruCache getInstance() {
        if (instance==null) {
            instance = new LruCache(100);
        }
        return instance;
    }

    private int cacheSize;
    private Map<String, Entry> nodes;// 缓存容器
    private Entry first;// 链表头
    private Entry last;// 链表尾

    public LruCache(int i) {
        cacheSize = i;
        nodes = new Hashtable<String, Entry>(i);//缓存容器
    }

    /**
     * 获取缓存中对象,并把它放在最前面
     */
    public <T> T get(String key) {
        Entry node = nodes.get(key);
        if (node != null) {
            if (System.currentTimeMillis()>node.validTime) {
                //在链表中删除
                remove(node);
                //在hashtable中删除
                nodes.remove(key);
            } else {
                moveToHead(node);
                return (T)node.value;
            }
        }
        return null;
    }

    /**
     * 加入缓存
     * 添加 entry到hashtable, 并把entry
     * @param key
     * @param timeout 超时时间,毫秒
     * @param value
     */
    public void put(String key,long timeout, Object value) {
        //先查看hashtable是否存在该entry, 如果存在,则只更新其value
        Entry node = nodes.get(key);

        if (node == null) {
            //缓存容器是否已经超过大小.
            if (nodes.size() >= cacheSize) {
                nodes.remove(last.key);
                removeLast();
            }
            node = new Entry();
        }
        node.validTime = System.currentTimeMillis() + timeout;
        node.value = value;
        //将最新使用的节点放到链表头,表示最新使用的.
        moveToHead(node);
        nodes.put(key, node);
    }

    /**
     * 将entry删除, 注意:删除操作只有在cache满了才会被执行
     */
    public void remove(String key) {
        Entry node = nodes.get(key);
        //在链表中删除
        remove(node);
        //在hashtable中删除
        nodes.remove(key);
    }

    private void remove(Entry node) {
        if (node != null) {
            if (node.prev != null) {
                node.prev.next = node.next;
            }
            if (node.next != null) {
                node.next.prev = node.prev;
            }
            if (last == node)
                last = node.prev;
            if (first == node)
                first = node.next;
        }
    }

    /**
     * 删除链表尾部节点,即使用最后 使用的entry
     */
    private void removeLast() {
        //链表尾不为空,则将链表尾指向null. 删除连表尾(删除最少使用的缓存对象)
        if (last != null) {
            if (last.prev != null)
                last.prev.next = null;
            else
                first = null;
            last = last.prev;
        }
    }

    /**
     * 移动到链表头,表示这个节点是最新使用过的
     */
    private void moveToHead(Entry node) {
        if (node == first)
            return;
        if (node.prev != null)
            node.prev.next = node.next;
        if (node.next != null)
            node.next.prev = node.prev;
        if (last == node)
            last = node.prev;
        if (first != null) {
            node.next = first;
            first.prev = node;
        }
        first = node;
        node.prev = null;
        if (last == null)
            last = first;
    }

    /*
     * 清空缓存
     */
    public void clear() {
        first = null;
        last = null;
        nodes = new Hashtable<String, Entry>(cacheSize);
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 02:34:03

8.16 lru缓存java版的相关文章

LRU缓存实现(Java)

LRU Cache的LinkedHashMap实现 LRU Cache的链表+HashMap实现 LinkedHashMap的FIFO实现 调用示例 LRU是Least Recently Used 的缩写,翻译过来就是"最近最少使用",LRU缓存就是使用这种原理实现,简单的说就是缓存一定量的数据,当超过设定的阈值时就把一些过期的数据删除掉,比如我们缓存10000条数据,当数据小于10000时可以随意添加,当超过10000时就需要把新的数据添加进来,同时要把过期数据删除,以确保我们最大缓

Java集合详解5:深入理解LinkedHashMap和LRU缓存

Java集合详解5:深入理解LinkedHashMap和LRU缓存 今天我们来深入探索一下LinkedHashMap的底层原理,并且使用linkedhashmap来实现LRU缓存. 具体代码在我的GitHub中可以找到 https://github.com/h2pl/MyTech 文章首发于我的个人博客: https://h2pl.github.io/2018/05/11/collection5 更多关于Java后端学习的内容请到我的CSDN博客上查看:https://blog.csdn.net

LRU缓存介绍与实现 (Java)

引子: 我们平时总会有一个电话本记录所有朋友的电话,但是,如果有朋友经常联系,那些朋友的电话号码不用翻电话本我们也能记住,但是,如果长时间没有联系 了,要再次联系那位朋友的时候,我们又不得不求助电话本,但是,通过电话本查找还是很费时间的.但是,我们大脑能够记住的东西是一定的,我们只能记住自己 最熟悉的,而长时间不熟悉的自然就忘记了. 其实,计算机也用到了同样的一个概念,我们用缓存来存放以前读取的数据,而不是直接丢掉,这样,再次读取的时候,可以直接在缓存里面取,而不用再重 新查找一遍,这样系统的反

转: LRU缓存介绍与实现 (Java)

引子: 我们平时总会有一个电话本记录所有朋友的电话,但是,如果有朋友经常联系,那些朋友的电话号码不用翻电话本我们也能记住,但是,如果长时间没有联系了,要再次联系那位朋友的时候,我们又不得不求助电话本,但是,通过电话本查找还是很费时间的.但是,我们大脑能够记住的东西是一定的,我们只能记住自己最熟悉的,而长时间不熟悉的自然就忘记了. 其实,计算机也用到了同样的一个概念,我们用缓存来存放以前读取的数据,而不是直接丢掉,这样,再次读取的时候,可以直接在缓存里面取,而不用再重新查找一遍,这样系统的反应能力

请用Java设计一个Least Recently Used (LRU) 缓存

LRU介绍:LRU是Least Recently Used的缩写,即最少使用页面置换算法,是为虚拟页式存储管理服务的, 思路介绍: 可以使用两个标准的数据结构来实现,Map和Queue.因为需要支持多线程,需要使用实现了java.utili.concurrent.*的Map和Queue. 主要思路是使用一个Queue来维护FIFO和Map来对数据进行排序,当向缓存添加新的元素时,共有以下三种可能 1. 如果该元素已经在Cache中存在(Map),我们会从queue中删除改元素并将其添加到queu

LeetCode 之 LRU Cache Java实现

LeetCode刷了41道题了,流程是按照戴兄的小书,很多不会的是参考Kim姐的代码,自己用Java抠腚的. 前几天做到了LRU Cache: C++的实现方法大同小异,大都用的是一个list加一个hash,hash中存储list节点地址,每次get从hash中寻key,有则将list相应节点放到链表头,没有则返回-1:每次set先判断hash中是否存在,存在则将相应节点移到表头,重置value值,如果不存在,判定长度是否达到预设的capacity,如果达到,删除表尾节点,新节点插入表头. 但是

JAVA版StarDict星际译王简单实现

由胡正开发的星际译王是Linux平台上很强大的一个开源的翻译软件(也有Windows版本的)支持多种词库.多种语言版本.尤其词库设计比较合理.之前看到一篇博文<星际译王词库应用-自制英汉词典>中用简短的程序就实现了词典的基本功能,不过那个是Linux 下的C/C++版本的,于是决定参考移植一个JAVA版本. import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream;

基于LinkedHashMap实现LRU缓存调度算法原理

引言 本文就 <基于LinkedHashMap实现LRU缓存调度算法原理及应用 >一文作为材料,记录一些常见问题,备忘. 延伸出两道常见的Java面试题: 插入Entry节点到table表的链表中时,Hashmap 和LinkedHashmap使用头茶法还是尾茶法?遍历map的时候,Entry.Entryset()获取的set集合,是按照从头到尾还是从尾到头的顺序存储的? 实现LRU算法最合适的数据结构? 如果读者可以打出来,不用继续看下边的资料了.初学者请继续阅读.相信你读完之后可以找到问题

动手写一个LRU缓存

前言 LRU 是 Least Recently Used 的简写,字面意思则是最近最少使用. 通常用于缓存的淘汰策略实现,由于缓存的内存非常宝贵,所以需要根据某种规则来剔除数据保证内存不被占满. 在redis的数据淘汰策略中就包含LRU淘汰算法 如何实现一个完整的LRU缓存呢?这个缓存要满足: 这个缓存要记录使用的顺序 随着缓存的使用变化,要能更新缓存的顺序 基于这种特点,可以使用一个常用的数据结构:链表 每次加入新的缓存时都添加到链表的头节点 当缓存再次被使用时移动缓存到头节点 当添加的缓存超