栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

自定义实现缓存带上过期时间

Java 更新时间:发布时间: 百科书网 趣学号

想着实现缓存,只是提供下思路,还有很多的问题,无法进行应用

public class LRUCache {

    // 链表节点的定义
    class LRUNode{
        String key;
        Object value;
        LRUNode next;
        LRUNode pre;
        // 假设都是毫秒
        Long expireTime;

        public LRUNode(String key, Object value,Long expireTime) {
            this.key = key;
            this.value = value;
            this.expireTime = expireTime;
        }

        @Override
        public String toString() {
            return "LRUNode{" +
                    "key='" + key + ''' +
                    ", value=" + value +
                    ", expireTime=" + expireTime +
                    '}';
        }
    }


    Map map = new HashMap<>();
    LRUNode head;
    LRUNode tail;
    // 缓存最大容量,我们假设最大容量大于 1,
    // 当然,小于等于1的话需要多加一些判断另行处理
    int capacity;

    public LRUCache(int capacity) {
        this.capacity = capacity;
    }

    public void getAll(){
        System.out.println("输出所有map的值");
        for (String key : this.map.keySet()){
            System.out.println(key + "=============" + this.map.get(key).toString());
        }

        System.out.println("输出当前node的双向链表的值");
        LRUNode temp = head;
        while(true){
            if (temp == null){
                break;
            }
            System.out.println(temp.toString());
            temp = temp.next;
        }
    }

    public synchronized void put(String key, Object value, Long expireTime) {
        // 简化处理,如果头部没数据,那么直接加入进去
        if (head == null) {
            head = new LRUNode(key, value, expireTime);
            tail = head;
            map.put(key, head);
        }
        // 如果内部有数据,通过map去查询出数据
        LRUNode node = map.get(key);
        // 如果node为空,那么往后续去添加
        if (node != null) {
            // 更新值,直接更新值
            node.value = value;
            // 更新过期时间
            node.expireTime = expireTime == null ? null : (System.currentTimeMillis() + expireTime);
            // 把他从链表删除并且插入到头结点
            removeAndInsert(node);
        } else {
            LRUNode tmp = new LRUNode(key, value, expireTime);
            // 如果会溢出
            if (map.size() >= capacity) {
                // 如果溢出了,那么就先查询过期的key进行删除
                LRUNode tempDeleteNode = tail;
                for (;;){
                    if (tempDeleteNode == null){
                        // 如果指针全部循环完成后,还是没有过期的,那么进行一波最后的尾部删除
                        map.remove(tail.key);
                        tail = tail.pre;
                        tail.next = null;
                        break;
                    }
                    if (tempDeleteNode.expireTime != null && tempDeleteNode.expireTime <= System.currentTimeMillis()){
                        map.remove(tempDeleteNode.key);
                        // 删除当前的节点
                        tempDeleteNode.pre.next = tempDeleteNode.next;
                        // 保证gc回收
                        tempDeleteNode = null;
                        break;
                    }
                    tempDeleteNode = tempDeleteNode.pre;
                }
            }
            map.put(key, tmp);
            // 插入
            tmp.next = head;
            head.pre = tmp;
            head = tmp;
        }
    }

    public Object get(String key) {
        LRUNode node = map.get(key);
        if (node != null) {
            // 把这个节点删除并插入到头结点
            removeAndInsert(node);
            return node.value;
        }
        return null;
    }
    private synchronized void removeAndInsert(LRUNode node) {
        // 特殊情况先判断,例如该节点是头结点或是尾部节点
        if (node == head) {
            return;
        } else if (node == tail) {
            tail = node.pre;
            tail.next = null;
        } else {
            node.pre.next = node.next;
            node.next.pre = node.pre;
        }
        // 插入到头结点
        node.next = head;
        node.pre = null;
        head.pre = node;
        head = node;
    }


    public static void main(String[] args) {
        LRUCache lruCache = new LRUCache(4);
        lruCache.put("key1","xxxxx",null);
        lruCache.put("key2",1111,null);
        // 这个是删除过期时间的
//        lruCache.put("key3","yyyyy",2L);
        // 这个是删除最后一位的
        lruCache.put("key3","yyyyy",null);
        lruCache.put("key4","object",null);
        lruCache.getAll();
        System.out.println("=========================");

        lruCache.put("key5", "zzzz",null);
        lruCache.getAll();
    }
}

参考一个大佬的文章,现在暂时找不到。。。如果有人发现,评论贴一下

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/275052.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号