LRU算法的实现

Posted jarjune

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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();
    }
}

搞定

以上是关于LRU算法的实现的主要内容,如果未能解决你的问题,请参考以下文章

LRU算法实现

LRU算法的实现

LinkedHashMap实现LRU算法

LRU(最近最少使用淘汰算法)基本实现

带你学会 LRU 算法相关内容

Java实现一个LRU算法