zoukankan      html  css  js  c++  java
  • 手写一个LruCache

    代码实现一 (直接继承ListHashMap.java)

    package org.java.write.lru;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
    
        private final int maxCapacity;
        private static final float DEFAULT_LOAD_FACTOR = 0.75f;
    
        private final Lock lock = new ReentrantLock();
    
        public LRULinkedHashMap(int maxCapacity) {
            super(maxCapacity, DEFAULT_LOAD_FACTOR, true);
            this.maxCapacity = maxCapacity;
        }
    
    
        //重新removeEldestEntry 方法 当前size大于maxCapacity时 删除最老的数据
        @Override
        protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
            return size() > maxCapacity;
        }
    
        @Override
        public boolean containsKey(Object key) {
            try {
                lock.lock();
                return super.containsKey(key);
            } finally {
                lock.unlock();
            }
        }
    
        @Override
        public V get(Object key) {
            try {
                lock.lock();
                ;
                return super.get(key);
            } finally {
                lock.unlock();
            }
        }
    
        @Override
        public V put(K key, V value) {
            try {
                lock.lock();
                return super.put(key, value);
            } finally {
                lock.unlock();
            }
        }
    
        @Override
        public int size() {
            try {
                lock.lock();
                return super.size();
            } finally {
                lock.unlock();
            }
        }
    
        @Override
        public void clear() {
            try {
                lock.lock();
                super.clear();
            } finally {
                lock.unlock();
            }
        }
    
        public Collection<Map.Entry<K, V>> getAll() {
            try {
                lock.lock();
                return new ArrayList<Map.Entry<K, V>>(super.entrySet());
            } finally {
                lock.unlock();
            }
        }
    
    }
    
    

    代码实现二

    package org.java.write.lru;
    
    import java.util.HashMap;
    import java.util.LinkedList;
    
    public class LruCache<K, V> {
        private int currentCacheSize;
        private int cacheCapacity;
        private HashMap<K, CacheNode<K, V>> caches;
        private CacheNode<K, V> first;
        private CacheNode<K, V> last;
    
        public LruCache(int size) {
            currentCacheSize = 0;
            this.cacheCapacity = size;
            caches = new HashMap<K, CacheNode<K, V>>(size);
        }
    
        public void put(K k, V v) {
            CacheNode<K, V> node = caches.get(k);
            //等于null 则代表缓存里没有数据 需要进行缓存
            if (node == null) {
                //如果超出范围 超出需要移除最后一个
                if (caches.size() >= cacheCapacity) {
                    caches.remove(last.key);
                    removeLast();
                }
            }
            //构建cacheNode  新构建的节点 应该是
            node = new CacheNode<K, V>();
            node.key = k;
            node.value = v;
            moveToFirst(node);
            caches.put(k, node);
            currentCacheSize++;
        }
    
        public V get(K k) {
            CacheNode<K, V> node = caches.get(k);
            if (node == null) {
                return null;
            }
            //将当前node 移动到首位
            moveToFirst(node);
            return node.value;
        }
    
        public V remove(K k) {
            CacheNode<K, V> node = caches.get(k);
            if (node != null) {
                //获取当前删除节点的前置节点,如果不为空 把前置节点的下一节点 置为当前删除节点的下一节点  (链表重新链接)
                if (node.pre != null) {
                    node.pre.next = node.next;
                }
                //获取当前删除节点的后置节点,如果不为空 把后置节点的前置节点 置位当前删除节点的上一节点(链表重新连接)
                if (node.next != null) {
                    node.next.pre = node.pre;
                }
                //判断当前删除节点是否是首节点 是的话 首节点需要变更 需要变更为当前删除节点的下一节点
                if (node == first) {
                    first = node.next;
                }
                //判断当前删除
                if (node == last) {
                    last = node.pre;
                }
                currentCacheSize--;
            }
            return caches.remove(k).value;
        }
    
        public void clear() {
            first = null;
            last = null;
            currentCacheSize = 0;
            cacheCapacity = 0;
            caches.clear();
        }
    
        private void moveToFirst(CacheNode<K, V> node) {
            //判断当前节点是否是首节点 初始化的时候 first 是null
            if (first == node) {
                return;
            }
            //自行想一下链表的结构
            if (node.next != null) {
                node.next.pre = node.pre;
            }
            //自行想一下链表的结构
            if (node.pre != null) {
                node.pre.next = node.next;
            }
            //如果节点是尾节点,
            if (node == last) {
                last = last.pre;
            }
            //如果first 节点和last节点都是空的  代表是缓存的第一个数据 需要将该节点设置为首节点和尾节点
            if (first == null || last == null) {
                first = last = node;
                return;
            }
            node.next = first;
            first.pre = node;
            first = node;
            first.pre = null;
        }
    
        /**
         * 移除最后一个元素
         */
        private void removeLast() {
            //最后一个元素是否为空
            if (last != null) {
                last = last.pre;
                if (last == null) {
                    first = null;
                } else {
                    last.next = null;
                }
            }
            currentCacheSize--;
        }
    
        static class CacheNode<K, V> {
            CacheNode<K, V> pre;
            CacheNode<K, V> next;
            K key;
            V value;
    
            public CacheNode() {
    
            }
        }
    
    }
    

    代码github write-lru-cache 分支

  • 相关阅读:
    SET TRANSACTION
    SET SESSION AUTHORIZATION
    SET CONSTRAINTS
    SET
    services
    send, sendto, sendmsg
    并列句分析
    cURL 学习笔记与总结(3)模拟登录博客园并下载个人随笔首页
    SQLServer2019安装教程
    Java实现 LeetCode 85 最大矩形
  • 原文地址:https://www.cnblogs.com/jakaBlog/p/11913304.html
Copyright © 2011-2022 走看看