LRU算法demo

星空.jpg

近期简单的看了些算法,印象深刻的lru算法,网上很多,贴了一个运行结果却不尽人意,以下自己单独写了一个,以便后期回顾

package LRU;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class LRUCache<V> {
    /**
     * 容量
     */
    private int capacity = 1024;
    /**
     * Node记录表
     */
    private Map<String, ListNode<String, V>> table = new ConcurrentHashMap<>();
    /**
     * 双向链表头部
     */
    private ListNode<String, V> head;
    /**
     * 双向链表尾部
     */
    private ListNode<String, V> tail;
    /**
     * 排序结果
     */
    private List orderList;


    public LRUCache(int capacity) {
        this();
        this.capacity = capacity;
    }


    public LRUCache() {
        head = new ListNode<>();
        tail = new ListNode<>();
        head.next = tail;
        head.prev = null;
        tail.prev = head;
        tail.next = null;
    }
    public void order(){
        List orderList = new ArrayList();
        ListNode<String, V> tag = new ListNode<String, V>();
        orderList.add(JSON.toJSONString(head.value));
        tag = head;
        while (null != tag.next.key){
            tag = tag.next;
            orderList.add(JSON.toJSONString(tag.value));
        }
        this.orderList = orderList;

    }


    public V get(String key) {
        ListNode<String, V> node = table.get(key);
        //重新连线[处理尾部]
        //尾部节点的前节点的前节点的下个节点指向尾部
        System.out.println("tail---->"+tail.key);
        tail.prev.prev.next=tail;
        //尾部节点指向前面节点的前节点
        System.out.println("tail.prev.prev---->"+tail.prev.prev.key);
        tail.prev=tail.prev.prev;

        System.out.println("tail.prev.key---->"+tail.prev.key);
        //重新连线[处理节点前后]
        //当前节点的下个节点的前节点指向当前节点的前节点
        node.next.prev=node.prev;
        //当前节点的前节点的下个节点指向当前节点的下个节点
        node.prev.next=node.next;
        //-------删除当前节点
        table.remove(key);
        //-------插入到头部
        //处理node尾部连线
        //头节点的下个节点的前节点插入node
        head.next.prev=node;
        //node的下个节点为当前头节点的下个节点
        node.next=head.next;
        //处理node头部连线
        //头节点的下个节点改为当前节点
        head.next=node;
        //当前节点的头节点设为头节点
        node.prev=head;
        table.put(key,node);

        return (V) node;
    }

    //插入前判断是否有大于缓存,如果大于则将尾部删除,头部插入新的节点
    //每次都从头插入
    //如果插入的值已存在则删除链表里面的节点,并将节点移动到头部
    public void put(String key, V value) {
        ListNode<String, V> nodeOld = table.get(key);
        if (nodeOld==null){
            ListNode<String, V> node = (ListNode<String, V>) value;
            if (table.size()>=capacity){
                //-------删除尾部
                table.remove(tail.prev.key);
                //重新连线
                //尾部节点的前节点的前节点的下个节点指向尾部
                System.out.println("tail---->"+tail.key);
                tail.prev.prev.next=tail;
                System.out.println("tail.prev.key---->"+tail.prev.key);

                //尾部节点指向前面节点的前节点
                System.out.println("tail.prev.prev---->"+tail.prev.prev.key);
                tail.prev=tail.prev.prev;


                //-------插入到头部
                //处理node尾部连线
                //头节点的下个节点的前节点插入node
                System.out.println("head.next.prev.key---->"+head.next.prev.key);
                head.next.prev=node;
                //node的下个节点为当前头节点的下个节点
                node.next=head.next;
                //处理node头部连线
                //头节点的下个节点改为当前节点
                System.out.println("head.next.key---->"+head.next.key);
                head.next=node;
                //当前节点的头节点设为头节点
                node.prev=head;
                table.put(key,node);
            }else {
                //-------插入到头部
                //处理node尾部连线
                //头节点的下个节点的前节点插入node
                head.next.prev=node;
                //node的下个节点为当前头节点的下个节点
                node.next=head.next;
                //如果tail的前节点是head证明是刚初始化,需要将node链接到tail
                if (tail.prev == head){
                    tail.prev = node;
                }
                //处理node头部连线
                //头节点的下个节点改为当前节点
                head.next=node;
                //当前节点的头节点设为头节点
                node.prev=head;
                table.put(key,node);
            }
        }else {
            //重新连线
            //当前节点的下个节点的前节点指向当前节点的前节点
            nodeOld.next.prev=nodeOld.prev;
            //当前节点的前节点的下个节点指向当前节点的下个节点
            nodeOld.prev.next=nodeOld.next;
            //-------删除当前节点
            table.remove(key);
            //-------插入到头部
            //处理node尾部连线
            //头节点的下个节点的前节点插入node
            head.next.prev=nodeOld;
            //node的下个节点为当前头节点的下个节点
            nodeOld.next=head.next;
            //处理node头部连线
            //头节点的下个节点改为当前节点
            head.next=nodeOld;
            //当前节点的头节点设为头节点
            nodeOld.prev=head;
            table.put(key,nodeOld);
        }



    }

    /**
     * 双向链表内部类
     */
    public static class ListNode<K, V> {
        private K key;
        private V value;
        ListNode<K, V> prev;
        ListNode<K, V> next;

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


        public ListNode() {

        }
    }




    public static void main(String[] args) {
        LRUCache<ListNode> cache = new LRUCache<>(4);
        ListNode<String, Integer> node1 = new ListNode<>("key1", 1);
        ListNode<String, Integer> node2 = new ListNode<>("key2", 2);
        ListNode<String, Integer> node3 = new ListNode<>("key3", 3);
        ListNode<String, Integer> node4 = new ListNode<>("key4", 4);
        ListNode<String, Integer> node5 = new ListNode<>("key5", 5);
        cache.put("key1", node1);
        cache.put("key2", node2);
        cache.put("key3", node3);
        cache.put("key4", node4);
        cache.put("key5", node5);
        //map没有顺序,不好看结果
        cache.order();
        System.out.println("head1-----------"+cache.head.next.key);
        System.out.println("tail1-----------"+cache.tail.prev.key);
        System.out.println("tail-----------"+ JSON.toJSONString(cache.orderList));
        cache.get("key2");
        cache.order();
        System.out.println("head1-----------"+cache.head.next.key);
        System.out.println("tail1-----------"+cache.tail.prev.key);
        System.out.println("tail-----------"+ JSON.toJSONString(cache.orderList));
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容