常见算法学习-LRU

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-05 05:35:01

Least Frequently Used 😆

简单原理和实现参考: 漫画:什么是LRU算法

简单版本

可以使用JDK自带的LinkedHashMap数据结构来实现

方法说明

//LinkedHashMap的一个构造函数,当参数accessOrder为true时,即会按照访问顺序排序,最近访问的放在最前,最早访问的放在后面
public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
}

//LinkedHashMap自带的判断是否删除最老的元素方法,默认返回false,即不删除老数据
//我们要做的就是重写这个方法,当满足一定条件时删除老数据
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
        return false;
}

实现方式

final int cacheSize = 100;
Map<String, String> map = new LinkedHashMap<String, String>((int) Math.ceil(cacheSize / 0.75f) + 1, 0.75f, true) {
    @Override
    protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
    return size() > cacheSize;
    }
};

手写版本

/**
 * LRU缓存实现
 *
 * @author Miguel.hou
 * @version v1.0
 * @date 2019-11-22
 */
public class LRUCache<V> {

    private Node<V> head;
    private Node<V> tail;
    private HashMap<String, Node<V>> hashMap;

    private Integer capacity;

    public LRUCache(Integer capacity) {
        if (capacity <= 0) {
            throw new IllegalArgumentException("capacity must greater than 0");
        }
        this.capacity = capacity;
        hashMap = new HashMap<>();
    }

    public synchronized V get(String key) {
        Node<V> node = hashMap.get(key);
        if (node == null) {
            return null;
        }

        // 刷新节点
        refreshNode(node);
        return node.value;
    }

    public synchronized void put(String key, V value) {
        Node<V> node = hashMap.get(key);
        if (node == null) {
            // 判断是否大于容量,需要去除首节点
            if (hashMap.size() >= capacity) {
                String rmKey = removeNode(head);
                hashMap.remove(rmKey);
            }
            // 加入队列
            Node<V> newNode = new Node<>(key, value);
            addNode(newNode);
            hashMap.put(key, newNode);
        } else {
            // node存在,刷新值
            node.value = value;
            refreshNode(node);
        }
    }

    public synchronized void remove(String key) {
        Node<V> node = hashMap.get(key);
        if (node == null) {
            return;
        }
        removeNode(node);
        hashMap.remove(key);
    }

    /**
     * 刷新节点位置
     * @param node
     */
    private void refreshNode(Node<V> node) {
        if (node == tail) {
            // 尾节点,不需要更新节点
            return;
        }

        // 删除节点
        removeNode(node);
        // 新增节点
        addNode(node);
    }

    private void addNode(Node<V> node) {
        if (tail != null) {
            tail.next = node;
            node.pre = tail;
            node.next = null;
        }
        tail = node;
        if (head == null) {
            head = node;
        }
    }

    private String removeNode(Node<V> node) {
        if (node == tail) {
            tail = node.pre;
        } else if (node == head) {
            head = node.next;
        } else {
            node.pre.next = node.next;
            node.next.pre = node.pre;
        }

        return node.key;
    }

    class Node<V> {
        public Node(String key, V value) {
            this.key = key;
            this.value = value;
        }

        Node<V> pre;
        Node<V> next;
        String key;
        V value;
    }

    public static void main(String[] args) {
        LRUCache<String> lruCache = new LRUCache<>(3);

        lruCache.put("001", "用户1信息");
        lruCache.put("002", "用户2信息");
        lruCache.put("003", "用户3信息");
        lruCache.put("004", "用户4信息");
        lruCache.put("005", "用户5信息");

        System.out.println(lruCache.get("004"));
        System.out.println(lruCache.get("003"));
        System.out.println(123);
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!