• LRU缓存


    实现摘要:map+双向链表

    Java中的LinkedHashMap本身自带lru属性。

    java实现:v1版本

    feature

    • 实现基本的lru语义
    • 不能扩容
    • evict回调
    • 范型
    public interface LruCache<K, V> {
       V get(K key);
       V put(K key, V value);
       V remove(K key);
       int size();
    }
    
    public class LruCacheImpl<K, V> implements LruCache<K, V> {
    
        static class Node<K, V> {
            Node<K, V> prev;
            Node<K, V> next;
            Node<K, V> nextE;
            K key;
            V value;
            public Node() {
    
            }
    
            public Node (Node<K, V> prev, Node<K, V> next, Node<K, V> nextE, K key, V value) {
                this.prev = prev;
                this.next = next;
                this.nextE = nextE;
                this.key = key;
                this.value = value;
            }
    
            @Override
            public String toString() {
    
                return "[key: " + key + ", value:" + value + "]";
            }
        }
    
        private Node<K, V> head = new Node<>(null, null, null, null, null), rear = head;
        private int threshold = 0, size = 0;
    
        public LruCacheImpl(int threshold) {
            this.threshold = threshold;
        }
    
        private int capacity = 128;
        private Node<K, V>[] bucket = new Node[capacity];
    
        @Override
        public V get(K key) {
            //计算hash
            int index = indexFor(key);
            Node<K, V> e;
            if ((e = bucket[index]) != null) {
                for (;e != null;) {
                    if (e.key == key || e.key.equals(key)) {
                        //adjust bi linked list
                        linkToLast(e);
                        return e.value;
                    }
                    e = e.nextE;
                }
            }
            return null;
        }
    
        @Override
        public V put(K key, V value) {
            //计算hash
            int index = indexFor(key);
            Node<K, V> e;
            if ((e = bucket[index]) != null) {
                for (;e != null;) {
                    if (e.key == key || e.key.equals(key)) {
                        V old = e.value;
                        e.value = value;
                        //adjust bi linked list
                        linkToLast(e);
                        return old;
                    }
                    e = e.nextE;
                }
            }
            //insert
            Node<K, V> node = new Node<>(rear, null,null, key, value);
            rear.next = node;
            rear = node;
            if (head.next == null) {
                head.next = node;
            }
            bucket[index] = node;
            size++;
            if (size > threshold) {
                int toDelNum = size - threshold;
                Node<K, V> p = head.next;
                for (int i = 0; i < toDelNum && p != null; i++, p = p.next) {
                    remove(p.key);
                    onEvict(p);
                }
            }
            return value;
        }
    
        //callback
        private void onEvict(Node<K,V> p) {
            System.out.println("evict : " + p);
        }
    
        private void linkToLast(Node<K,V> e) {
            if (e == rear) return;
            //先删除该节点
            e.next.prev = e.prev;
            e.prev.next = e.next;
    
            rear.next = e;
            e.next = null;
            e.prev = rear;
    
            rear = e;
        }
    
        private int indexFor(K key) {
            int hash = key.hashCode();
            return hash % capacity;
        }
    
        @Override
        public V remove(K key) {
            //计算hash
            int index = indexFor(key);
            Node<K, V> e;
            if ((e = bucket[index]) != null) {
                if (e.key == key || e.key.equals(key)) {
                    bucket[index] = e.nextE;
                } else {
                    for (Node<K, V> pre = e, cur = e.nextE; cur != null; pre = cur, cur = cur.nextE) {
                        if (cur.key == key || cur.key.equals(key)) {
                            //delete node @ bi linked list
                            pre.nextE = cur.nextE;
                            cur.nextE = null;
                            e = cur;
                            break;
                        }
                    }
                }
                //delete e @ bi linked list
                size--;
    
                if (e == rear) {
                    rear = e.prev;
                    rear.next = null;
                } else {
                    e.prev.next = e.next;
                    e.next.prev = e.prev;
                }
                e.next = null;
                e.prev = null;
                return e.value;
            }
            return null;
        }
    
        @Override
        public int size() {
            return size;
        }
    
        public void list() {
            StringBuilder sb = new StringBuilder();
            for (Node<K, V> e = head.next; e != null; e = e.next) {
                sb.append("
    [key=").append(e.key).append(", value=").append(e.value).append("]");
            }
            System.out.println(sb.toString());
        }
    }
    
    
  • 相关阅读:
    ubuntu 启动 重启 停止 apache
    /usr/bin/env: php: No such file or directory 【xunsearch demo项目体验】【已解决】
    安装mezzanine时报:storing debug log for failure【已解决】
    redhat 安装 setuptools【成功】
    SnowNLP:一个处理中文文本的 Python 类库[转]
    Android 了解1G 2G 3G 知识
    Android-体系架构
    Android-bindService远程服务(Aidl)-初步
    Android-SDCard外部存储文件读写
    Android-文件模式
  • 原文地址:https://www.cnblogs.com/Spground/p/9744415.html
Copyright © 2020-2023  润新知