import java.util.*;


public class Solution {
        class Node {
            int key;
            int value;
            Node pre;
            Node next;

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

        // cache
        HashMap<Integer, Node> map;
        // 记录最长时间没使用的节点
        Node head;
        // 记录最后使用的节点
        Node tail;

        // cache 长度
        int capacity;

        public Solution(int capacity) {
            this.capacity = capacity;
            map = new HashMap<>(capacity);
        }

        public int get(int key) {
            Node node = map.get(key);
            if (node == null) {
                return -1;
            }
            // 节点之前存在了,然后被使用了需要移动到链表的尾部
            moveNode(node);
            return node.value;
        }

        public void set(int key, int value) {
            Node node = map.get(key);
            if (node == null) {
                // 节点之前不存在
                node = new Node(key, value);
                if (head == null) {
                    head = node;
                } else {
                    node.pre = tail;
                    tail.next = node;
                }
                tail = node;
            } else {
                // 节点之前已经存在了,更新值,然后移动位置
                node.value = value;
                moveNode(node);
            }
            map.put(key, node);
            // put进去后,缓存超过capacity,需要将头结点移除
            removeCacheIfNecessary();
        }

        private void removeCacheIfNecessary() {
            if (map.size() > capacity) {
                Node delete = head;
                head = head.next;
                delete.next =null;
                head.pre = null;
                map.remove(delete.key);
            }
        }

        /**
         * 将节点移动到链表尾部
         * @param node 要移动的节点
         */
        private void moveNode(Node node) {
            if (node == head && head.next != null) {
                // 要移动的节点时头节点,且节点的长度不为1
                head = head.next;
                head.pre = null;
                tail.next = node;
                node.pre = tail;
                tail = node;
                node.next = null;
                return;
            }
            if (tail != node) {
                // 要移动的节点不是头,也不是尾
                Node pre = node.pre;
                Node next = node.next;
                pre.next = next;
                next.pre = pre;
                tail.next = node;
                node.pre = tail;
                tail = node;
                node.next = null;
            }
            // 要移动的节点时尾节点,不需要移动
        }
    }

/**
 * Your Solution object will be instantiated and called as such:
 * Solution solution = new Solution(capacity);
 * int output = solution.get(key);
 * solution.set(key,value);
 */

map + 双向链表的结构,给是使用数据后,把使用的数据移动到链表的最尾部,具体可以看代码中的注释