Created
June 23, 2018 16:35
-
-
Save afghl/c43da734818f76a58456c8b615171c62 to your computer and use it in GitHub Desktop.
A LRU cache implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package cache; | |
import java.util.HashMap; | |
import java.util.Map; | |
public class LRUCache { | |
private static final int NOTHING = -1; | |
private int capacity; | |
private int size; | |
private Map<Integer, Node> map = new HashMap<>(); | |
private DoubleLinkedList linkedList = DoubleLinkedList.DEFAULT; | |
public LRUCache(int capacity) { | |
this.capacity = capacity; | |
this.size = 0; | |
} | |
public int get(int key) { | |
Node node = map.get(key); | |
if (node == null) { | |
return NOTHING; | |
} | |
touch(node); | |
return node.value; | |
} | |
public void put(int key, int value) { | |
Node node = map.get(key); | |
if (node == null) { | |
node = linkedList.insertHead(nodeOf(key, value)); | |
map.put(node.key, node); | |
size++; | |
} else { | |
node.value = value; | |
touch(node); | |
} | |
if (size > capacity) | |
limitCapacity(); | |
} | |
private void limitCapacity() { | |
Node node = linkedList.removeTail(); | |
removeInMap(node); | |
size = capacity; | |
} | |
private void removeInMap(Node node) { | |
map.remove(node.key); | |
} | |
private void touch(Node node) { | |
linkedList.moveToHead(node); | |
} | |
private Node nodeOf(int key, int value) { | |
return new Node(key, value); | |
} | |
private static class DoubleLinkedList { | |
private Node head; | |
private Node tail; | |
private static final DoubleLinkedList DEFAULT = new DoubleLinkedList(); | |
public void moveToHead(Node node) { | |
insertHead(removeNode(node)); | |
} | |
public Node insertHead(Node node) { | |
node.next = head; | |
if (head != null) { | |
head.prev = node; | |
} | |
head = node; | |
if (tail == null) { | |
tail = head; | |
} | |
return head; | |
} | |
public Node removeTail() { | |
return removeNode(tail); | |
} | |
private Node removeNode(Node node) { | |
if (node.prev != null) { | |
node.prev.next = null; | |
} | |
if (node.next != null) { | |
node.next.prev = null; | |
} | |
if (node == tail) { | |
tail = node.prev; | |
} | |
return node; | |
} | |
} | |
private class Node { | |
private Node prev; | |
private Node next; | |
private int key; | |
private int value; | |
private Node(int key, int value) { | |
this.key = key; | |
this.value = value; | |
this.prev = null; | |
this.next = null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment