最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中的LinkedHashMap及LRU緩存機(jī)制詳解

 更新時間:2023年09月19日 10:04:00   作者:強(qiáng)欽欽  
這篇文章主要介紹了Java中的LinkedHashMap及LRU緩存機(jī)制詳解,LinkedHashMap繼承自HashMap,它的多種操作都是建立在HashMap操作的基礎(chǔ)上的,同HashMap不同的是,LinkedHashMap維護(hù)了一個Entry的雙向鏈表,保證了插入的Entry中的順序,需要的朋友可以參考下

LinkedHashMap

  1. 維持插入順序;如 (1,“a”) (2, “b”)(先插的先訪問)
  2. 維持訪問順序(將最近訪問的數(shù)據(jù)移到鏈表的尾部 LRU思想 afterNodeAccess(里面處理了Entry的before after屬性))
  3. 主要是底層維護(hù)了一個雙向鏈表
  4. 不能被克隆和序列化(HashMap可以)
  5. LinkedHashMap的put類似于HashMap的 ; LinkedKeyIterator里調(diào)用nextNode() 源碼716行 modcount fast-fail

實(shí)現(xiàn)LRU緩存機(jī)制

  • Least Recently Used的縮寫,即最近最少使用
  • LRU緩存機(jī)制類似LinkedHashMap的雙向鏈表
  • LRU緩存:內(nèi)存訪問時,設(shè)計一個緩存(如內(nèi)存4G,其中1G設(shè)置為緩存),大小固定,讀取內(nèi)存數(shù)據(jù),首先會去找緩存是否命中
    • 如果命中,直接返回
    • 反之,未命中從內(nèi)存中讀取數(shù)據(jù),把數(shù)據(jù)繼續(xù)添加到緩存當(dāng)中,
    • 如果緩存已滿,刪除訪問時間最早的數(shù)據(jù)

代碼測試驗(yàn)證看下面的LRU代碼。

1)使用LinkedHashMap實(shí)現(xiàn)LRU緩存

需要重寫removeEldestEntry方法,該方法:

a. 通過 返回結(jié)果 去刪除訪問 時間最早 的數(shù)據(jù)

b. map的size()與給定緩存的最大size比較,如果map.size > MaxSize,則return true

c. 參數(shù)Map.Entry<K,V> eldest

package collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
class LRUCache<K,V> extends LinkedHashMap<K,V>{
    private int maxSize; //緩存的大小
    //重寫
    public LRUCache(int maxSize){
        super(16, 0.75f, true);
        this.maxSize = maxSize;
    }
    //protected
    @Override
    protected boolean removeEldestEntry(Map.Entry<K,V> eldest){
        return size() > maxSize;//根據(jù)大小,決定是否刪除最早結(jié)點(diǎn)
    }
}
public class Teacher_1_15_LinkedHashMap {
    public static void main(String[] args) {
    	//使用LinkedHashMap實(shí)現(xiàn)LRU緩存
    	//大小為3
        LRUCache<String, String> cache = new LRUCache<>(3);
        cache.put("a", "jfdshjhf");
        //a
        cache.put("b", "fdjhfjf");
        //a - > b
        cache.put("c", "all");
        //a -> b -> c
        cache.get("a");
        //b -> c -> a
        cache.put("d", "tulun");
        //c -> a -> d
        System.out.println(cache);
        //維護(hù)插入順序
//        LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
//        map.put(1, "ajhd");
//        map.put(5, "fsd");
//        map.put(12, "ref");
//        map.put(10, "gdfs");
//        map.put(19, "hgf");
//        map.put(21, "hgf");
//
//        Iterator<Integer> iterator = map.keySet().iterator();
//        while(iterator.hasNext()){
//            System.out.println(iterator.next());
//        }
//        //維持訪問順序                                                                                                                                                                                             加載因子:f類型      accessOrder
//        LinkedHashMap<Integer, String> map = new LinkedHashMap<Integer, String>(16, 0.75f, true);
//        map.put(1, "ajhd");
//        map.put(5, "fsd");
//        map.put(12, "ref");
//        map.put(10, "gdfs");
//        map.put(19, "hgf");
//        map.put(21, "hgf");
//
//        map.get(12);
//        map.get(10);
//
//        Iterator<Integer> iterator = map.keySet().iterator();
//        while(iterator.hasNext()){
//            System.out.println(iterator.next());
//        }
    }
}

2)簡單的自定義實(shí)現(xiàn)(筆試)

設(shè)置頭結(jié)點(diǎn) 尾節(jié)點(diǎn)

存數(shù)據(jù)的容器:HashMap

維護(hù)雙向鏈表,確保 數(shù)據(jù)按照訪問時間存儲

package collection;
import java.util.HashMap;
import javax.swing.text.html.HTMLDocument.Iterator;
class MyLRUCache<K,V>{
    private Node<K,V> head = new Node<>();//頭結(jié)點(diǎn)    無參構(gòu)造
    private Node<K,V> tail = new Node<>();//尾
    private final HashMap<Integer,Node> hashMap = new HashMap<>();//new了,作為容器
    private int size;  //實(shí)際大小
    private int capacity;//最大容量
    class Node<K, V>{
        private K key;
        private V value;
        private Node pre;//雙向鏈表
        private Node next;
        //構(gòu)造器
        public Node(){
        }
        public Node(K key, V value){
            this.key = key;
            this.value = value;
        }
    }
    //初始化
    public MyLRUCache(int capacity){
        head.next = tail;//先指向無效的結(jié)點(diǎn),專門指向 頭和尾
        tail.pre = head;
        this.capacity = capacity;
        size = 0;
    }
    //添加某個節(jié)點(diǎn)(尾插法)
    private void add(Node node){
    	//put里已判斷key是否存在,這里只管添加
    	//空表
    	if(tail.pre==head) {
    		head.next=node;//由head指向node
    		//node為首結(jié)點(diǎn),前面再無,故不用設(shè)置node.pre
    		tail.pre=node;
    	}else {
    		//Tail之后添加
    		node.pre=tail.pre;
    		tail.pre.next=node;
    		tail.pre=node;
    	}	
    }
    //刪除某個節(jié)點(diǎn)
    private void remove(Node node){
    	//非空表
    	if(head.next!=tail) {//比地址
    		//頭結(jié)點(diǎn)
    		if(node==head.next) {
        		head.next=head.next.next; //新頭結(jié)點(diǎn)
        		//head.next.pre=null; //新頭結(jié)點(diǎn)不需要設(shè)置pre
        	}else if(node==tail.pre) {
        		//尾結(jié)點(diǎn)
        		tail.pre=tail.pre.pre;//新尾結(jié)點(diǎn)
        		//tail.pre.pre.next=null;
        	}else {
        		//其他
        		node.pre.next=node.next;//要刪除結(jié)點(diǎn)的前面結(jié)點(diǎn)的next指針往后指一個
            	node.next.pre=node.pre;//要刪除結(jié)點(diǎn)的后面結(jié)點(diǎn)的 pre指針往前指一個
        	}   
    	}	
    }
    //添加key-value鍵值對
    public void put(K key, V value){
        Node node = hashMap.get(key);//hashMap里已存有相同key的結(jié)點(diǎn)
        if(node != null){
            node.value = value;
            //從鏈表中刪除node節(jié)點(diǎn)
            remove(node);
            //再將node節(jié)點(diǎn)尾插法重新插入鏈表(因?yàn)樗鼊偙辉L問)
            add(node);
        }else{
            if(size < capacity){
                size++;
            }else{
                //超容量(1個),刪除緩存中最近最少使用的節(jié)點(diǎn)head.next
            	//注意先從HashMap里刪除,不然remove會改變head.next值
            	hashMap.remove(head.next.key);//刪除指定key的結(jié)點(diǎn)
            	remove(head.next);//head.next變?yōu)橹赶騢ead.next.next了
            }
            //將newNode尾插法插入鏈表
            Node newNode = new Node(key, value);//將輸入的key value包裝成node
            hashMap.put((Integer) key, newNode);//存到hashMap,鍵為隨機(jī)值,值為node結(jié)點(diǎn)        (int)(Math.random()*100)
            add(newNode);
        }
    }
    //獲取value(返回8,表示成功)(將訪問的元素移到鏈表尾)
    public int get(K key){
        Node node = hashMap.get(key);
        if(node == null){
            return -1;
        }
        //刪除node
        hashMap.remove(node.key);//刪除指定key的結(jié)點(diǎn)
        remove(node);
        //尾插法重新插入
        add(node);
        hashMap.put((Integer) key, node);
        //等價于個數(shù)沒變
        return 8;
    }
    public void show() {
    	Node<K,V> temp = head;
    	while(temp!=tail.pre){//tail.pre指向的是末尾節(jié)點(diǎn)
    		temp=temp.next;
    		System.out.print(temp.key+"  ");
    	}
    	System.out.println();
    }
}
public class Teacher_1_15_MyLRUCache {
    public static void main(String[] args) {
      //維護(hù)插入順序
      MyLRUCache<Integer, String> cache = new MyLRUCache<>(3);
      cache.put(1, "ajhd");
      cache.put(5, "fsd");
      cache.put(12, "ref");
      cache.show();//應(yīng)該1 5  12
      System.out.println(cache.get(5));//成功則返回8
      cache.show(); //應(yīng)該1 12 5
      cache.put(10, "gdfs");
      cache.show();//應(yīng)該12 5 10
      //如何打印雙向鏈表里的順序
      System.out.println(cache.get(1));
    }
}

到此這篇關(guān)于Java中的LinkedHashMap及LRU緩存機(jī)制詳解的文章就介紹到這了,更多相關(guān)LinkedHashMap及LRU緩存機(jī)制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot后端如何實(shí)現(xiàn)攜帶token登陸

    springboot后端如何實(shí)現(xiàn)攜帶token登陸

    這篇文章主要介紹了springboot后端如何實(shí)現(xiàn)攜帶token登陸,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • SpringBoot2零基礎(chǔ)到精通之JUnit 5與指標(biāo)監(jiān)控

    SpringBoot2零基礎(chǔ)到精通之JUnit 5與指標(biāo)監(jiān)控

    SpringBoot是一種整合Spring技術(shù)棧的方式(或者說是框架),同時也是簡化Spring的一種快速開發(fā)的腳手架,本篇讓我們一起學(xué)習(xí)JUnit 5與指標(biāo)監(jiān)控
    2022-03-03
  • Java OOP三大特征之封裝繼承與多態(tài)詳解

    Java OOP三大特征之封裝繼承與多態(tài)詳解

    本文主要講述的是面向?qū)ο蟮娜筇匦裕悍庋b,繼承,多態(tài),內(nèi)容含括從封裝到繼承再到多態(tài)的所有重點(diǎn)內(nèi)容以及使用細(xì)節(jié)和注意事項(xiàng),內(nèi)容有點(diǎn)長,請大家耐心看完
    2022-07-07
  • JSR-107緩存規(guī)范介紹

    JSR-107緩存規(guī)范介紹

    JSR是Java Specification Requests的縮寫,意思是Java規(guī)范提案,下面給大家介紹JSR-107緩存規(guī)范的相關(guān)知識,感興趣的朋友一起看看吧
    2025-05-05
  • Flutter實(shí)現(xiàn)文本組件、圖標(biāo)及按鈕組件的代碼

    Flutter實(shí)現(xiàn)文本組件、圖標(biāo)及按鈕組件的代碼

    這篇文章主要介紹了Flutter實(shí)現(xiàn)文本組件、圖標(biāo)及按鈕組件的代碼,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2019-07-07
  • Java 1.0和Java 1.1 的IO類的比較

    Java 1.0和Java 1.1 的IO類的比較

    Java庫的IO分為輸入/輸出兩部分。早期的Java 1.0版本的輸入系統(tǒng)是InputStream及其子類,輸出系統(tǒng)是OutputStream及其子類。后來的Java 1.1版本對IO系統(tǒng)進(jìn)行了重新設(shè)計。本分對此做了分析和比較,有利于學(xué)習(xí),最后給出了例子。
    2013-11-11
  • SpringBoot validator參數(shù)驗(yàn)證restful自定義錯誤碼響應(yīng)方式

    SpringBoot validator參數(shù)驗(yàn)證restful自定義錯誤碼響應(yīng)方式

    這篇文章主要介紹了SpringBoot validator參數(shù)驗(yàn)證restful自定義錯誤碼響應(yīng)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 深入了解Java ServletContext

    深入了解Java ServletContext

    這篇文章主要介紹了Java ServletContext的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-08-08
  • SpringBoot配置Https入門實(shí)踐

    SpringBoot配置Https入門實(shí)踐

    本文主要介紹了SpringBoot配置Https入門實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-11-11
  • Java枚舉與注解的創(chuàng)建步驟

    Java枚舉與注解的創(chuàng)建步驟

    這篇文章通過抽象的概念和具體實(shí)現(xiàn)步驟,充分說明了java枚舉與注解的概念和使用方法,通過該篇文章你可以學(xué)會如何自定義枚舉類和了解部分Java內(nèi)置注解,希望對你有所幫助
    2021-06-06

最新評論

兴安县| 房产| 安义县| 扬州市| 光山县| 西吉县| 永吉县| 五寨县| 威宁| 米脂县| 晋中市| 苗栗县| 普洱| 河间市| 侯马市| 大关县| 九寨沟县| 平南县| 南漳县| 巢湖市| 元朗区| 珠海市| 通化市| 亚东县| 东源县| 邯郸市| 江陵县| 太白县| 闸北区| 措勤县| 鄂温| 双鸭山市| 六枝特区| 类乌齐县| 灯塔市| 余江县| 荃湾区| 金溪县| 鹤山市| 正安县| 余庆县|