在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Map類(lèi)集合基本元素的實(shí)現(xiàn)演變

科技綠洲 ? 來(lái)源:Java技術(shù)指北 ? 作者:Java技術(shù)指北 ? 2023-10-10 16:14 ? 次閱讀

說(shuō)到集合類(lèi),之前介紹的ArrayList類(lèi),HashMap可能是大家日常用的最多的類(lèi),但是對(duì)于另一個(gè)集合類(lèi) LinkedHashMap,可能大家用的不多,但是這種鏈?zhǔn)焦<?,有些情況確實(shí)特別好用。

1、LinkedHashMap 定義

LinkedHashMap 是基于 HashMap 實(shí)現(xiàn)的一種集合,具有 HashMap 集合上面所說(shuō)的所有特點(diǎn),除了 HashMap 無(wú)序的特點(diǎn),LinkedHashMap 是有序的,因?yàn)?LinkedHashMap 在 HashMap 的基礎(chǔ)上單獨(dú)維護(hù)了一個(gè)具有所有數(shù)據(jù)的雙向鏈表,該鏈表保證了元素迭代的順序。

所以我們可以直接這樣說(shuō):LinkedHashMap = HashMap + LinkedList。LinkedHashMap 就是在 HashMap 的基礎(chǔ)上多維護(hù)了一個(gè)雙向鏈表,用來(lái)保證元素迭代順序。

更形象化的圖形展示可以直接移到文章末尾。

public class LinkedHashMap< K,V >
    extends HashMap< K,V >
    implements Map< K,V >

圖片

2、字段屬性

①、Entry

static class Entry< K,V > extends HashMap.Node< K,V > {
        Entry< K,V > before, after;
        Entry(int hash, K key, V value, Node< K,V > next) {
            super(hash, key, value, next);
        }
    }

LinkedHashMap 的每個(gè)元素都是一個(gè) Entry,我們看到對(duì)于 Entry 繼承自 HashMap 的 Node 結(jié)構(gòu),相對(duì)于 Node 結(jié)構(gòu),LinkedHashMap 多了 before 和 after 結(jié)構(gòu)。

下面是Map類(lèi)集合基本元素的實(shí)現(xiàn)演變。

圖片

LinkedHashMap 中 Entry 相對(duì)于 HashMap 多出的 before 和 after 便是用來(lái)維護(hù) LinkedHashMap 插入 Entry 的先后順序的。

②、其它屬性

//用來(lái)指向雙向鏈表的頭節(jié)點(diǎn)
transient LinkedHashMap.Entry< K,V > head;
//用來(lái)指向雙向鏈表的尾節(jié)點(diǎn)
transient LinkedHashMap.Entry< K,V > tail;
//用來(lái)指定LinkedHashMap的迭代順序
//true 表示按照訪問(wèn)順序,會(huì)把訪問(wèn)過(guò)的元素放在鏈表后面,放置順序是訪問(wèn)的順序
//false 表示按照插入順序遍歷
final boolean accessOrder;

注意:這里有五個(gè)屬性別搞混淆的,對(duì)于 Node next 屬性,是用來(lái)維護(hù)整個(gè)集合中 Entry 的順序。對(duì)于 Entry before,Entry after ,以及 Entry head,Entry tail,這四個(gè)屬性都是用來(lái)維護(hù)保證集合順序的鏈表,其中前兩個(gè)before和after表示某個(gè)節(jié)點(diǎn)的上一個(gè)節(jié)點(diǎn)和下一個(gè)節(jié)點(diǎn),這是一個(gè)雙向鏈表。后兩個(gè)屬性 head 和 tail 分別表示這個(gè)鏈表的頭節(jié)點(diǎn)和尾節(jié)點(diǎn)。

3、構(gòu)造函數(shù)

①、無(wú)參構(gòu)造

public LinkedHashMap() {
        super();
        accessOrder = false;
    }

調(diào)用無(wú)參的 HashMap 構(gòu)造函數(shù),具有默認(rèn)初始容量(16)和加載因子(0.75)。并且設(shè)定了 accessOrder = false,表示默認(rèn)按照插入順序進(jìn)行遍歷。

②、指定初始容量

public LinkedHashMap(int initialCapacity) {
        super(initialCapacity);
        accessOrder = false;
    }

③、指定初始容量和加載因子

public LinkedHashMap(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor);
        accessOrder = false;
    }

4、添加元素

LinkedHashMap 中是沒(méi)有 put 方法的,直接調(diào)用父類(lèi) HashMap 的 put 方法。關(guān)于 HashMap 的put 方法,可以參看我之前對(duì)于 HashMap 的介紹。

我將方法介紹復(fù)制到下面:

//hash(key)就是上面講的hash方法,對(duì)其進(jìn)行了第一步和第二步處理
   public V put(K key, V value) {
       return putVal(hash(key), key, value, false, true);
   }
   /**
    *
    * @param hash 索引的位置
    * @param key  鍵
    * @param value  值
    * @param onlyIfAbsent true 表示不要更改現(xiàn)有值
    * @param evict false表示table處于創(chuàng)建模式
    * @return
    */
   final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
           boolean evict) {
        Node< K,V >[] tab; Node< K,V > p; int n, i;
        //如果table為null或者長(zhǎng)度為0,則進(jìn)行初始化
        //resize()方法本來(lái)是用于擴(kuò)容,由于初始化沒(méi)有實(shí)際分配空間,這里用該方法進(jìn)行空間分配,后面會(huì)詳細(xì)講解該方法
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        //注意:這里用到了前面講解獲得key的hash碼的第三步,取模運(yùn)算,下面的if-else分別是 tab[i] 為null和不為null
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);//tab[i] 為null,直接將新的key-value插入到計(jì)算的索引i位置
        else {//tab[i] 不為null,表示該位置已經(jīng)有值了
            Node< K,V > e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;//節(jié)點(diǎn)key已經(jīng)有值了,直接用新值覆蓋
            //該鏈?zhǔn)羌t黑樹(shù)
            else if (p instanceof TreeNode)
                e = ((TreeNode< K,V >)p).putTreeVal(this, tab, hash, key, value);
            //該鏈?zhǔn)擎湵?/span>
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        //鏈表長(zhǎng)度大于8,轉(zhuǎn)換成紅黑樹(shù)
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    //key已經(jīng)存在直接覆蓋value
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;//用作修改和新增快速失敗
        if (++size > threshold)//超過(guò)最大容量,進(jìn)行擴(kuò)容
            resize();
        afterNodeInsertion(evict);
        return null;
   }

5、刪除元素

同理也是調(diào)用 HashMap 的remove 方法,這里我不作過(guò)多的講解,著重看LinkedHashMap 重寫(xiě)的第 46 行方法。

public V remove(Object key) {
        Node< K,V > e;
        return (e = removeNode(hash(key), key, null, false, true)) == null ?
            null : e.value;
    }

    final Node< K,V > removeNode(int hash, Object key, Object value,
            boolean matchValue, boolean movable) {
        Node< K,V >[] tab; Node< K,V > p; int n, index;
        //(n - 1) & hash找到桶的位置
        if ((tab = table) != null && (n = tab.length) > 0 &&
        (p = tab[index = (n - 1) & hash]) != null) {
        Node< K,V > node = null, e; K k; V v;
        //如果鍵的值與鏈表第一個(gè)節(jié)點(diǎn)相等,則將 node 指向該節(jié)點(diǎn)
        if (p.hash == hash &&
        ((k = p.key) == key || (key != null && key.equals(k))))
        node = p;
        //如果桶節(jié)點(diǎn)存在下一個(gè)節(jié)點(diǎn)
        else if ((e = p.next) != null) {
            //節(jié)點(diǎn)為紅黑樹(shù)
        if (p instanceof TreeNode)
         node = ((TreeNode< K,V >)p).getTreeNode(hash, key);//找到需要?jiǎng)h除的紅黑樹(shù)節(jié)點(diǎn)
        else {
         do {//遍歷鏈表,找到待刪除的節(jié)點(diǎn)
             if (e.hash == hash &&
                 ((k = e.key) == key ||
                  (key != null && key.equals(k)))) {
                 node = e;
                 break;
             }
             p = e;
         } while ((e = e.next) != null);
        }
        }
        //刪除節(jié)點(diǎn),并進(jìn)行調(diào)節(jié)紅黑樹(shù)平衡
        if (node != null && (!matchValue || (v = node.value) == value ||
                      (value != null && value.equals(v)))) {
        if (node instanceof TreeNode)
         ((TreeNode< K,V >)node).removeTreeNode(this, tab, movable);
        else if (node == p)
         tab[index] = node.next;
        else
         p.next = node.next;
        ++modCount;
        --size;
        afterNodeRemoval(node);
        return node;
        }
        }
        return null;
    }

6、查找元素

public V get(Object key) {
        Node< K,V > e;
        if ((e = getNode(hash(key), key)) == null)
            return null;
        if (accessOrder)
            afterNodeAccess(e);
        return e.value;
    }

相比于 HashMap 的 get 方法,這里多出了第 5,6行代碼,當(dāng) accessOrder = true 時(shí),即表示按照最近訪問(wèn)的迭代順序,會(huì)將訪問(wèn)過(guò)的元素放在鏈表后面。

對(duì)于 afterNodeAccess(e) 方法,在前面第 4 小節(jié) 添加元素已經(jīng)介紹過(guò)了,這就不在介紹。

7、遍歷元素

在介紹 HashMap 時(shí),我們介紹了 4 中遍歷方式,同理,對(duì)于 LinkedHashMap 也有 4 種,這里我們介紹效率較高的兩種遍歷方式:

①、得到 Entry 集合,然后遍歷 Entry

LinkedHashMap< String,String > map = new LinkedHashMap<  >();
        map.put("A","1");
        map.put("B","2");
        map.put("C","3");
        map.get("B");
        Set< Map.Entry< String,String >> entrySet = map.entrySet();
        for(Map.Entry< String,String > entry : entrySet ){
            System.out.println(entry.getKey()+"---"+entry.getValue());
        }

②、迭代

Iterator< Map.Entry< String,String >> iterator = map.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry< String,String > entry = iterator.next();
            System.out.println(entry.getKey()+"----"+entry.getValue());
        }

8、小結(jié)

好了,這就是JDK中java.util.LinkedHashMap 類(lèi)的介紹。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)
    +關(guān)注

    關(guān)注

    8

    文章

    7149

    瀏覽量

    89600
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4346

    瀏覽量

    62981
  • MAP
    MAP
    +關(guān)注

    關(guān)注

    0

    文章

    49

    瀏覽量

    15184
  • 元素
    +關(guān)注

    關(guān)注

    0

    文章

    47

    瀏覽量

    8471
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    【labview我來(lái)告訴你】實(shí)現(xiàn)任何LabVIEW數(shù)據(jù)類(lèi)型集合的簡(jiǎn)潔方式

    則是元素排列按一定順序的集合。Variant attributes 提供了一個(gè)非常好而簡(jiǎn)潔的方式來(lái)實(shí)現(xiàn)任何 LabVIEW 數(shù)據(jù)類(lèi)型的集合。 比如我們想創(chuàng)建一個(gè)字符串的有序
    發(fā)表于 12-30 09:30

    【labview我來(lái)告訴你】簡(jiǎn)潔的實(shí)現(xiàn)任何 LabVIEW 數(shù)據(jù)類(lèi)型的集合

    而簡(jiǎn)潔的方式來(lái)實(shí)現(xiàn)任何 LabVIEW 數(shù)據(jù)類(lèi)型的集合。 比如我們想創(chuàng)建一個(gè)字符串的有序集合,我們可以通過(guò)使用Set Variant Attribute 來(lái)追加新的元素迚去。作為 Va
    發(fā)表于 01-11 09:52

    簡(jiǎn)潔的實(shí)現(xiàn)任何 LabVIEW 數(shù)據(jù)類(lèi)型的集合

    而簡(jiǎn)潔的方式來(lái)實(shí)現(xiàn)任何 LabVIEW 數(shù)據(jù)類(lèi)型的集合。 比如我們想創(chuàng)建一個(gè)字符串的有序集合,我們可以通過(guò)使用Set Variant Attribute 來(lái)追加新的元素迚去。作為 Va
    發(fā)表于 12-17 09:51

    java集合干貨系列

    :List列表、Set集合、Map映射、工具類(lèi)(Iterator迭代器、Enumeration枚舉類(lèi)、Arrays和Collections)。  Collection接口、子接口以及
    發(fā)表于 12-14 15:11

    干貨!對(duì) buck-boost 進(jìn)行演變,最終會(huì)演變成 flyback

    演變成更復(fù)雜的拓?fù)浣Y(jié)構(gòu),那么我們?nèi)跁?huì)貫通的理解各種拓?fù)浣Y(jié)構(gòu),就變得非常容易。其實(shí)理解隔離電源,相對(duì)非隔離DCDC來(lái)說(shuō),需要多理解一個(gè)基本元素——變壓器。然后很多基本原理也可以通過(guò)基本拓?fù)溥M(jìn)行演變。本文
    發(fā)表于 01-12 16:09

    python入門(mén)知識(shí):什么是set集合

    集合set set集合是一個(gè)無(wú)序不重復(fù)元素的集,基本功能包括關(guān)系測(cè)試和消除重復(fù)元素集合使用大括號(hào)({})框定
    發(fā)表于 09-24 16:29

    python集合

    python集合集合(英文名 set),它是一個(gè)無(wú)序的不重復(fù)元素序列。這里面有兩個(gè)重點(diǎn):無(wú)序,不重復(fù)1. 創(chuàng)建集合集合的創(chuàng)建有兩種方法第一種方法:使用 花括號(hào) {} 直接創(chuàng)建,創(chuàng)建的時(shí)候,{} 可以
    發(fā)表于 02-23 17:04

    HarmonyOS方舟開(kāi)發(fā)框架容器類(lèi)API的介紹與使用

    作者:liuxin,華為高級(jí)工程師 容器類(lèi),顧名思義就是存儲(chǔ)的類(lèi),用于存儲(chǔ)各種數(shù)據(jù)類(lèi)型的元素,并具備一系列處理數(shù)據(jù)元素的方法。在方舟開(kāi)發(fā)框架中,容器
    發(fā)表于 03-07 11:40

    JAVA集合類(lèi)匯總

    多數(shù)情況下使用。 二、層次關(guān)系 如圖所示:圖中,實(shí)線邊框的是實(shí)現(xiàn)類(lèi),折線邊框的是抽象類(lèi),而點(diǎn)線邊框的是接口 Collection 接口是集合類(lèi)
    的頭像 發(fā)表于 01-16 11:50 ?3835次閱讀
    JAVA<b class='flag-5'>集合</b><b class='flag-5'>類(lèi)</b>匯總

    數(shù)組與集合類(lèi)說(shuō)明

    對(duì)數(shù)組與集合類(lèi)進(jìn)行詳細(xì)介紹。
    發(fā)表于 03-17 14:28 ?6次下載
    數(shù)組與<b class='flag-5'>集合</b><b class='flag-5'>類(lèi)</b>說(shuō)明

    什么是 map

    map 容器,又稱鍵值對(duì)容器,即該容器的底層是以紅黑樹(shù)變體實(shí)現(xiàn)的,是典型的關(guān)聯(lián)式容器。這意味著,map 容器中的元素可以分散存儲(chǔ)在內(nèi)存空間里,而不是必須存儲(chǔ)在一整塊連續(xù)的內(nèi)存空間中。跟
    的頭像 發(fā)表于 02-27 15:41 ?3134次閱讀

    python集合表達(dá)式及方法

    python數(shù)字的集合(set)類(lèi)型,是無(wú)序集合集合中的元素(項(xiàng))不會(huì)重復(fù),不管添加多少個(gè)相同元素(項(xiàng)),只會(huì)保存1次。
    的頭像 發(fā)表于 03-10 10:06 ?1388次閱讀

    Java8的Stream流 map() 方法

    之后,對(duì)集合可以進(jìn)行 Stream 操作,使上面的處理更簡(jiǎn)潔。 概述 Stream 流式處理中有 map() 方法,先看下其定義,該方法在java.util.stream.Stream類(lèi)中 可以看到
    的頭像 發(fā)表于 09-25 11:06 ?2033次閱讀
    Java8的Stream流 <b class='flag-5'>map</b>() 方法

    List 轉(zhuǎn) Map的方法

    在我們平時(shí)的工作中,充滿了各種類(lèi)型之間的轉(zhuǎn)換。今天小編帶大家上手 List 轉(zhuǎn) Map 的各種操作。 我們將假設(shè) List 中的每個(gè)元素都有一個(gè)標(biāo)識(shí)符,該標(biāo)識(shí)符將在生成的 Map 中作為一個(gè)鍵
    的頭像 發(fā)表于 10-09 16:10 ?1703次閱讀

    LinkedHashSet 和 LinkedHashMap定義

    Map 類(lèi)集合實(shí)現(xiàn)了 Set 類(lèi)集合。 1、LinkedHashSet 定義 LinkedHa
    的頭像 發(fā)表于 10-10 15:10 ?550次閱讀
    LinkedHashSet 和 LinkedHashMap定義
    主站蜘蛛池模板: 久久澳门 | 国产黄视频在线观看 | 色碰人色碰人视频 | 丁香花免费观看视频 | 奇米影视狠狠 | 丁香花高清在线观看 | 欧美午夜色大片在线观看免费 | 久久99精品久久久久久园产越南 | 天天躁夜夜躁狠狠躁2021a | 超薄肉色丝袜精品足j福利 超黄视频在线观看 | 国产精品美女视频 | 日日碰狠狠添天天爽五月婷 | 日本午夜色 | 优优优色| 成人拍拍视频 | 国模谢心2013.05.06私拍 | 成人影院在线观看视频 | 在线黄色免费网站 | 伊人久久成人爱综合网 | 狠狠要 | 97干干 | 欧美怡红院免费全视频 | 狠狠色96视频 | 国产视频每日更新 | 一级毛片一片毛 | 六月丁香深爱六月综合激情 | 末成年一级在线看片 | 手机在线你懂的 | 素股中文字幕 | 欧美日韩不卡码一区二区三区 | 色综合成人网 | 91破处视频| 日本老师xxxxxxxxx79 | 欧美透逼视频 | 女同在线视频 | 四虎永久免费影院 | 手机看片福利日韩国产 | 欧美性操| 女人张开腿让男人桶视频免费大全 | 国产 日韩 欧美 高清 | 亚洲午夜免费视频 |