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算法。

  • 相关阅读:
    【xsy1230】 树(tree) 点分治+线段树
    【xsy1237】 字符转换 矩阵快速幂
    【xsy1232】Magic 最小割
    【xsy1144】选物品 主席树
    【xsy3423】党² 线段树+李超线段树or动态半平面交
    $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
    $Django redis内存数据库 (知识回顾cmd切换目录)
    $Django 路飞之课程下的分类,用户登陆成功前端存cookie,
    $Django 路飞之小知识回顾,Vue之样式element-ui,Vue绑定图片--mounted页面挂载--路由携带参数
    $Django 路飞学城项目简介
  • 原文地址:https://www.cnblogs.com/strongmore/p/14460307.html
Copyright © 2011-2022 走看看