码迷,mamicode.com
首页 > 编程语言 > 详细

LRU算法的实现

时间:2020-11-24 12:37:52      阅读:8      评论:0      收藏:0      [点我收藏+]

标签:链表   等于   row   ==   双向链表   package   头结点   hash   else   

缘由:看到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算法的实现

标签:链表   等于   row   ==   双向链表   package   头结点   hash   else   

原文地址:https://www.cnblogs.com/jarjune/p/14010351.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!