亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

LinkedHashMap如何保證有序問題

 更新時(shí)間:2022年11月21日 08:34:11   作者:小小少年_  
這篇文章主要介紹了LinkedHashMap如何保證有序問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

LinkedHashMap如何保證有序

我們常說linkedHashMap是有序的,這個(gè)有序也是分為兩種的,分別是:插入順序和訪問順序,我們可以通俗的認(rèn)為:linkedHashMap = hashmap + 雙向鏈表

以下的學(xué)習(xí)是基于jdk8

在這里插入圖片描述

根據(jù)linkedHashMap的結(jié)構(gòu)來看,是依賴于hashmap的,通過查看源碼,我們也會(huì)發(fā)現(xiàn),linkedHashMap只是維護(hù)了一個(gè)鏈表,并沒有put、remove方法的具體實(shí)現(xiàn),

因?yàn)閘inkedHashMap的設(shè)計(jì)思想是:對(duì)數(shù)據(jù)的操作,是依賴于hashmap中的方法,只是在其中的一些細(xì)節(jié)方法,linkedHashMap會(huì)進(jìn)行擴(kuò)展,接下來我們先說屬性有哪些

屬性信息

/**
     * The head (eldest) of the doubly linked list.
     * 鏈表的head節(jié)點(diǎn)
     */
    transient LinkedHashMap.Entry<K,V> head;

    /**
     * The tail (youngest) of the doubly linked list.
     * 鏈表的尾結(jié)點(diǎn)
     */
    transient LinkedHashMap.Entry<K,V> tail;

    /**
     * The iteration ordering method for this linked hash map: <tt>true</tt>
     * for access-order, <tt>false</tt> for insertion-order.
     * false:表示插入順序;true表示讀取順序
     * @serial
     */
    final boolean accessOrder;

AccessOrder

該屬性是來區(qū)分當(dāng)前l(fā)inkedHashMap是按照訪問順序排序,還是按照put順序有序,當(dāng)該參數(shù)為true的時(shí)候,表示按照讀取順序有序;默認(rèn)為false,按照put順序有序

newNode()

在調(diào)用put方法的時(shí)候,會(huì)調(diào)用父類hashmap的put方法,那linkedHashMap如何維護(hù)節(jié)點(diǎn)之間的順序呢?

在put方法中,如果得到當(dāng)前key要存儲(chǔ)的位置,會(huì)調(diào)用newNode()方法,初始化一個(gè)node節(jié)點(diǎn),

在這里插入圖片描述

linkedHashMap對(duì)該方法,進(jìn)行了覆寫,

/**
     * 在向map中put元素的時(shí)候,是會(huì)初始化一個(gè)node節(jié)點(diǎn),如果是linkedHashMap,調(diào)用的是該方法
     * 在該方法中,可以看到,會(huì)初始化一個(gè)LinkedHashMap.Entry節(jié)點(diǎn),然后將該節(jié)點(diǎn)插入到linkedHashMap的雙向鏈表中
     * 默認(rèn)是加到鏈表尾部
     * @param hash
     * @param key
     * @param value
     * @param e
     * @return
     */
    Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
        LinkedHashMap.Entry<K,V> p =
            new LinkedHashMap.Entry<K,V>(hash, key, value, e);
        linkNodeLast(p);
        return p;
    }

這里可以看到,除了初始化一個(gè)節(jié)點(diǎn)之外,還會(huì)調(diào)用linkNodeLast方法,在linkedNodeLast方法中,會(huì)將p節(jié)點(diǎn)添加到自己維護(hù)的雙向鏈表的尾部

/**
     * 這是加入到鏈表尾部的方法
     * 如果當(dāng)前是第一個(gè)put的元素,那p就是head,否則,就把節(jié)點(diǎn)放到tail的后面
     * @param p
     */
    private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
        LinkedHashMap.Entry<K,V> last = tail;
        tail = p;
        if (last == null)
            head = p;
        else {
            p.before = last;
            last.after = p;
        }
    }

按訪問順序有序

假如在初始化linkedHashMap對(duì)象的時(shí)候,指定accessOrder為true,那表示按照訪問順序有序,在get方法中,會(huì)對(duì)訪問到的元素進(jìn)行處理

public V get(Object key) {
        Node<K,V> e;
        // 這里的getNode調(diào)用的是hashmap中的方法,獲取到當(dāng)前key所對(duì)應(yīng)的value
        if ((e = getNode(hash(key), key)) == null)
            return null;
        /**
         * 如果是按照訪問順序有序,會(huì)把獲取到的e節(jié)點(diǎn)插入到鏈表的尾部,然后返回e.value
         */
        if (accessOrder)
            afterNodeAccess(e);
        return e.value;
    }

這里可以看到,如果是按照訪問順序有序的話,會(huì)額外調(diào)用afterNodeAccess()方法,如果為false,會(huì)直接返回獲取到的節(jié)點(diǎn)value值,afterNodeAccess方法簡單而言,就是將e節(jié)點(diǎn)移到鏈表的尾部,所以,我們可以認(rèn)為,最近訪問的在元素在鏈表的最后面

所以:對(duì)于按照put順序有序的設(shè)置,在put元素的時(shí)候,本身就會(huì)把最新插入的元素放入到鏈表的尾部,如果是按照訪問順序有序的話,在get的時(shí)候,會(huì)把訪問的元素移到鏈表的尾部,根據(jù)該特點(diǎn),也可以實(shí)現(xiàn)一個(gè)簡單的LRU算法

對(duì)于hashmap和linkedHashMap來說,最大的區(qū)別就是:hashmap是無序的,linkedHashMap自己維護(hù)了節(jié)點(diǎn)的順序

LinkedHashMap實(shí)現(xiàn)有序的原理

LinkedHashMap采用的hash算法和HashMap相同,但是它重新定義了數(shù)組中保存的元素Entry,該Entry除了保存當(dāng)前對(duì)象的引用外,還保存了其上一個(gè)元素before和下一個(gè)元素after的引用,從而在哈希表的基礎(chǔ)上又構(gòu)成了雙向鏈接列表。

這樣就能按照插入的順序遍歷原本無序的HashMap了,是不是很方便?

看源代碼:

/** 
 * 雙向鏈表的表頭元素。 
 */  
private transient Entry<K,V> header;  
  
/** 
 * LinkedHashMap的Entry元素。 
 * 繼承HashMap的Entry元素,又保存了其上一個(gè)元素before和下一個(gè)元素after的引用。 
 */  
private static class Entry<K,V> extends HashMap.Entry<K,V> {  
    Entry<K,V> before, after;  
    ……  
}  

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java項(xiàng)目中的絕對(duì)路徑和相對(duì)路徑用法說明

    java項(xiàng)目中的絕對(duì)路徑和相對(duì)路徑用法說明

    這篇文章主要介紹了java項(xiàng)目中的絕對(duì)路徑和相對(duì)路徑用法說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • Java實(shí)現(xiàn)四則混合運(yùn)算代碼示例

    Java實(shí)現(xiàn)四則混合運(yùn)算代碼示例

    這篇文章主要介紹了Java實(shí)現(xiàn)四則混合運(yùn)算代碼示例,文中展示了詳細(xì)代碼,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-10-10
  • Mybatis實(shí)現(xiàn)查詢相冊(cè)數(shù)據(jù)列表流程講解

    Mybatis實(shí)現(xiàn)查詢相冊(cè)數(shù)據(jù)列表流程講解

    這篇文章主要介紹了Mybatis實(shí)現(xiàn)查詢相冊(cè)數(shù)據(jù)列表流程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-12-12
  • Java平閏年判斷的方法總結(jié)

    Java平閏年判斷的方法總結(jié)

    本篇文章給大家整理了Java平閏年判斷的兩種方法,大家在寫程序的時(shí)候如果用的到參考下吧。
    2018-02-02
  • SpringBoot異常處理之異常顯示的頁面問題

    SpringBoot異常處理之異常顯示的頁面問題

    這篇文章主要介紹了SpringBoot異常處理異常顯示的頁面的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-09-09
  • Java多線程環(huán)境下死鎖模擬

    Java多線程環(huán)境下死鎖模擬

    這篇文章主要介紹了模擬Java多線程環(huán)境下的死鎖,文章介紹一些死鎖的產(chǎn)生條件的相關(guān)資料,具有一定的參考價(jià)值,需要的小伙伴可以參考一下,希望對(duì)你有所幫助
    2021-12-12
  • 詳談Java泛型中T和問號(hào)(通配符)的區(qū)別

    詳談Java泛型中T和問號(hào)(通配符)的區(qū)別

    下面小編就為大家?guī)硪黄斦凧ava泛型中T和問號(hào)(通配符)的區(qū)別。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • Flask實(shí)現(xiàn)異步非阻塞請(qǐng)求功能實(shí)例解析

    Flask實(shí)現(xiàn)異步非阻塞請(qǐng)求功能實(shí)例解析

    這篇文章主要介紹了Flask實(shí)現(xiàn)異步非阻塞請(qǐng)求功能實(shí)例解析,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • 最全MyBatis核心配置文件總結(jié)(收藏)

    最全MyBatis核心配置文件總結(jié)(收藏)

    這篇文章主要介紹了最全MyBatis核心配置文件總結(jié)(收藏),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 使用Java如何對(duì)復(fù)雜的數(shù)據(jù)類型排序和比大小

    使用Java如何對(duì)復(fù)雜的數(shù)據(jù)類型排序和比大小

    我相信大家在第一次接觸算法的時(shí)候,最先接觸的肯定也是從排序算法開始的,下面這篇文章主要給大家介紹了關(guān)于使用Java如何對(duì)復(fù)雜的數(shù)據(jù)類型排序和比大小的相關(guān)資料,需要的朋友可以參考下
    2023-12-12

最新評(píng)論