LRU实现

用双端链表实现,将每次最新插入或者最新访问的节点移动到链表的尾部

当容量满的时候,直接移除首节点就可以了。同时要注意一些边界情况-----链表只有一个节点。

import java.util.HashMap;

public class LRU {

	public static class Node<K, V> {
		private K key;
		private V value;
		private Node<K, V> pre;
		private Node<K, V> next;

		public Node(K key, V value) {
			this.key = key;
			this.value = value;
		}
	}

	public static class NodeDoubleLinkedList<K, V> {
		private Node<K, V> head;
		private Node<K, V> tail;

		public NodeDoubleLinkedList() {
			this.head = null;
			this.tail = null;
		}

		/**
		 * 将一个节点插入到双向链表 新节点的插入都从尾部进行。即尾部的节点是最近使用
		 * 
		 * @Title: addNode
		 * @Description: TODO
		 * @param: @param newNode
		 * @return: void
		 */
		public void addNode(Node<K, V> newNode) {
			if (newNode == null) {
				return;
			}
			// 当头结点为null说明现在是一个空链表
			if (this.head == null) {
				this.head = newNode;
				this.tail = newNode;
			} else {
				this.tail.next = newNode;
				newNode.pre = this.tail;
				this.tail = newNode;
			}
		}

		/**
		 * 将一个节点移动到链表尾部 在查询到该节点的时候要进行移动
		 * 
		 * @Title: moveNodeToTail
		 * @Description: TODO
		 * @param: @param moveNode
		 * @return: void
		 */
		public void moveNodeToTail(Node<K, V> moveNode) {
			if (this.tail == moveNode) {
				return;
			}
			if (this.head == moveNode) {// 移动的节点是头结点
				this.head = moveNode.next;
				this.head.pre = null;
			} else {// 移动的节点是普通节点
				moveNode.next.pre = moveNode.pre;
				moveNode.pre.next = moveNode.next;
			}
			moveNode.pre = this.tail;
			moveNode.next = null;
			this.tail.next = moveNode;
			this.tail = moveNode;
		}

		/**
		 * 当容量到了的时候从链表的头部进行删除
		 * 
		 * @Title: removeNode
		 * @Description: TODO
		 * @param: @return
		 * @return: Node<K,V>
		 */
		public Node<K, V> removeNode() {
			if (this.head == null) {
				return null;
			}
			Node<K, V> res = this.head;
			if (this.head == this.tail) {
				this.head = null;
				this.tail = null;
			} else {
				this.head = res.next;
				res.next = null;
				this.head.pre = null;
			}
			return res;
		}
	}

	
	public static class LRUCache<K, V> {
		private HashMap<K, Node<K, V>> keyNodeMap;
		private NodeDoubleLinkedList<K, V> nodeList;
		private int capacity;

		public LRUCache(int capacity) {
			if (capacity < 1) {
				throw new RuntimeException("容量应该大于0");
			}
			this.capacity = capacity;
			this.keyNodeMap = new HashMap<K, Node<K, V>>();
			this.nodeList = new NodeDoubleLinkedList<K, V>();
		}

		public V get(K key) {
			if (this.keyNodeMap.containsKey(key)) {
				Node<K, V> res = keyNodeMap.get(key);
				this.nodeList.moveNodeToTail(res);
				return res.value;
			}
			return null;
		}

		public void set(K key, V value) {
			if (this.keyNodeMap.containsKey(key)) {
				Node node = this.keyNodeMap.get(key);
				node.value = value;
				this.nodeList.moveNodeToTail(node);
			} else {
				Node<K, V> newNode = new Node<K, V>(key, value);
				keyNodeMap.put(key, newNode);
				this.nodeList.addNode(newNode);
				if (this.keyNodeMap.size() == this.capacity + 1) {
					this.removeMostUnusedCache();
				}
			}
		}

		public void removeMostUnusedCache() {
			Node<K, V> removeNode = this.nodeList.removeNode();
			K removeKey = removeNode.key;
			this.keyNodeMap.remove(removeKey);
			System.out.println(removeKey);
		}
	}

	public static void main(String[] args) {
		LRUCache<String, Integer> testCache = new LRUCache<String, Integer>(2);
		testCache.set("A", 111);
		testCache.set("B", 222);
		testCache.get("A");
		testCache.set("C", 333);
		testCache.set("D", 444);
	}

}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值