zoukankan      html  css  js  c++  java
  • LRU算法的实现

    缘由:看到redis的缓存淘汰机制,便自己实现了一下

    代码实现(双向链表+HashMap)

    package com.jarjune.jdalao.framework.algorithm;
    
    import java.util.*;
    
    /**
     * LRU
     * @author jarjune
     * @version 1.0.1
     * @date 2020/11/19
     */
    public class LRUCache<K, V> {
    
        // 缓存Node
        private Map<K, Node<K, V>> cache;
    
        // 双向链表首结点
        private Node<K, V> first;
    
        // 双向链表尾结点
        private Node<K, V> last;
    
        // 最大缓存容量
        private int capacity;
    
        public LRUCache(int capacity) throws Exception {
            if(capacity < 2) {
                throw new Exception("capacity小于2就没啥意义了...");
            }
            this.cache = new HashMap<>((int) (capacity / 0.75f + 1));
            this.capacity = capacity;
        }
    
        private class Node<K, V> {
            K k;
            V v;
            Node<K, V> prev;
            Node<K, V> next;
    
            Node(K k, V v) {
                this.k = k;
                this.v = v;
            }
    
            @Override
            public String toString() {
                return "Node{" +
                        "k=" + k +
                        ", v=" + v +
                        '}';
            }
        }
    
        public int size() {
            return cache.size();
        }
    
        public void put(K k, V v) {
    
            Node<K, V> node = cache.get(k);
            if(null == node) {
                node = new Node<>(k, v);
    
                // 大于等于capacity容量最大值时
                if(cache.size() >= capacity) {
    
                    if(null != last) {
                        // 移除最后一个元素的缓存
                        cache.remove(last.k);
    
                        last = last.prev;
                        if(null == last) {
                            first = null;
                        } else {
                            last.next = null;
                        }
                    }
                }
                cache.put(k, node);
            } else {
                node.v = v;
            }
    
            moveToFirst(node);
        }
    
        /**
         *  1(first)
         * ↑  ↓
         *  2(node)
         * ↑  ↓
         *  3
         * ↑  ↓
         *  4(last)
         */
        private void moveToFirst(Node<K, V> node) {
    
            if(first == null || last == null) {
                first = last = node;
                return;
            }
    
            // 如果是头结点就结束
            if(node == first) {
                return;
            }
    
            // 如果是尾结点,尾结点就等于当前结点的上一个结点
            if(node == last) {
                last = node.prev;
            }
    
            if(null != node.next) {
                node.next.prev = node.prev;
            }
    
            if(null != node.prev) {
                node.prev.next = node.next;
            }
    
            node.next = first;
            first.prev = node;
            node.prev = null;
            first = node;
        }
    
        class LRUIterable implements Iterable<Node<K, V>> {
    
            @Override
            public Iterator<Node<K, V>> iterator() {
                return new Iterator<Node<K, V>>() {
    
                    private Node<K, V> node = first;
    
                    @Override
                    public boolean hasNext() {
                        return node != null;
                    }
    
                    @Override
                    public Node<K, V> next() {
                        Node<K, V> tmp = node;
                        node = node.next;
                        return tmp;
                    }
                };
            }
        }
    
        public Iterator<Node<K, V>> iterator() {
            return new LRUIterable().iterator();
        }
    
        public Set<K> keySet() {
            Iterator<Node<K, V>> iterator = iterator();
            Set<K> keys = new LinkedHashSet<>();
            while(iterator.hasNext()) {
                keys.add(iterator.next().k);
            }
            return keys;
        }
    
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            for (Node<K, V> node: new LRUIterable()) {
                sb.append(node);
            }
            return sb.toString();
        }
    }
    
    

    搞定

  • 相关阅读:
    全排列问题(内测第0届第1题)
    提取字符串中的数字(C语言)
    尾递归=递归+迭代?
    Android各版本代号、版本号、API/NDK级别、发布时间及市场份额
    C语言中文件打开模式(r/w/a/r+/w+/a+/rb/wb/ab/rb+/wb+/ab+)浅析
    sizeof既是关键字,又是运算符(操作符),但不是函数!
    探寻main函数的“标准”写法,以及获取main函数的参数、返回值
    Scala比较器:Ordered与Ordering
    【Python实战】Pandas:让你像写SQL一样做数据分析(一)
    【Python实战】Scrapy豌豆荚应用市场爬虫
  • 原文地址:https://www.cnblogs.com/jarjune/p/14010351.html
Copyright © 2011-2022 走看看