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

    简介

    LRU(Least recently used),即最近最少使用,核心思想是如果数据最近被访问过,那么将来被访问的几率也更高。

    代码实现1

    import java.util.LinkedHashMap;
    import java.util.Map.Entry;
    
    class LRUCache<K, V> {
    
      private LinkedHashMap<K, V> map;
    
      public LRUCache(int capacity) {
        map = new LinkedHashMap<>(capacity, 0.75f, true) {
          @Override
          protected boolean removeEldestEntry(Entry<K, V> eldest) {
            return size() > capacity;
          }
        };
      }
    
      public V get(K key) {
        return map.get(key);
      }
    
      public void put(K key, V value) {
        map.put(key, value);
      }
    
      public static void main(String[] args) {
        LRUCache<Integer, Integer> lRUCache = new LRUCache<>(2);
        lRUCache.put(1, 1); // 缓存是 {1=1}
        lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
        System.out.println(lRUCache.get(1));//返回 1 缓存是 {2=2,1=1}
        lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
        System.out.println(lRUCache.get(2));// 返回 null (未找到)
        lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {3=3,4=4}
        System.out.println(lRUCache.get(1));//返回 null (未找到)
        System.out.println(lRUCache.get(3));//返回 3
        System.out.println(lRUCache.get(4));//返回 4
      }
    }
    

    LRU算法主要有两种操作添加put和获取get,需要使用到哈希表和双向链表两种数据结构,java内置的LinkedHashMap结合了这两种。访问一个元素之后就会将该元素移动到链表的末尾,如果添加元素之后发现超出容量,删除链表头部的元素。

    代码实现2

    import java.util.HashMap;
    
    class LRUCache2<K, V> {
    
      private HashMap<K, Node<K, V>> cache;
      private Node<K, V> head;
      private Node<K, V> tail;
      private int capacity;
    
      public LRUCache2(int capacity) {
        this.capacity = capacity;
        cache = new HashMap<>(capacity);
      }
    
      public V get(K key) {
        Node<K, V> node = cache.get(key);
        if (node == null) {
          return null;
        }
        moveToTail(node);
        return node.value;
      }
    
      public void put(K key, V value) {
        Node<K, V> node = cache.get(key);
        if (node != null) {
          node.value = value;
          moveToTail(node);
        } else {
          Node<K, V> newNode = new Node<>(key, value);
          cache.put(key, newNode);
          addToTail(newNode);
          //如果超出容量,删除链表头结点
          if (cache.size() > capacity) {
            cache.remove(head.key);
            removeNode(head);
          }
        }
      }
    
      /**
       * 将e节点移动到链表尾部
       */
      private void moveToTail(Node<K, V> e) {
        removeNode(e);
        addToTail(e);
      }
    
      private void addToTail(Node<K, V> e) {
        //将e链接到tail后面
        if (tail == null) {
          head = e;
        } else {
          tail.next = e;
          e.prev = tail;
        }
        tail = e;
      }
    
      private void removeNode(Node<K, V> e) {
        Node<K, V> prev = e.prev;
        Node<K, V> next = e.next;
        //删除e节点
        e.prev = e.next = null;
        if (prev == null) {
          head = next;
        } else {
          prev.next = next;
        }
        if (next == null) {
          tail = prev;
        } else {
          next.prev = prev;
        }
      }
    
      static class Node<K, V> {
    
        K key;
        V value;
        Node<K, V> prev;
        Node<K, V> next;
    
        Node(K key, V value) {
          this.key = key;
          this.value = value;
        }
      }
    
      public static void main(String[] args) {
        LRUCache2<Integer, Integer> lRUCache = new LRUCache2<>(2);
        lRUCache.put(1, 1); // 缓存是 {1=1}
        lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
        System.out.println(lRUCache.get(1));//返回 1 缓存是 {2=2,1=1}
        lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
        System.out.println(lRUCache.get(2));// 返回 null (未找到)
        lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {3=3,4=4}
        System.out.println(lRUCache.get(1));//返回 null (未找到)
        System.out.println(lRUCache.get(3));//返回 3
        System.out.println(lRUCache.get(4));//返回 4
      }
    }
    

    通过自己实现的双向链表和java的哈希表来实现LRU算法。

  • 相关阅读:
    二叉树进阶之寻找一棵二叉树中的最大二叉搜索子树
    二叉树进阶之求一棵二叉树中结点间最大距离
    软件工程各阶段的UML图
    软件工程各阶段的开发文档
    二叉树应用进阶之折纸(二叉树的右根左遍历)
    二叉树进阶应用之查找结点的后继结点
    二叉树进阶之满二叉树和完全二叉树
    二叉树进阶之搜索二叉树的判断与找出搜索二叉树中出错的结点
    二叉树进阶之平衡二叉树的判断
    二叉树基础之序列化和反序列化二叉树
  • 原文地址:https://www.cnblogs.com/strongmore/p/14460307.html
Copyright © 2011-2022 走看看