色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Map類集合基本元素的實現演變

科技綠洲 ? 來源:Java技術指北 ? 作者:Java技術指北 ? 2023-10-10 16:14 ? 次閱讀

說到集合類,之前介紹的ArrayList類,HashMap可能是大家日常用的最多的類,但是對于另一個集合類 LinkedHashMap,可能大家用的不多,但是這種鏈式哈希集合,有些情況確實特別好用。

1、LinkedHashMap 定義

LinkedHashMap 是基于 HashMap 實現的一種集合,具有 HashMap 集合上面所說的所有特點,除了 HashMap 無序的特點,LinkedHashMap 是有序的,因為 LinkedHashMap 在 HashMap 的基礎上單獨維護了一個具有所有數據的雙向鏈表,該鏈表保證了元素迭代的順序。

所以我們可以直接這樣說:LinkedHashMap = HashMap + LinkedList。LinkedHashMap 就是在 HashMap 的基礎上多維護了一個雙向鏈表,用來保證元素迭代順序。

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

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 的每個元素都是一個 Entry,我們看到對于 Entry 繼承自 HashMap 的 Node 結構,相對于 Node 結構,LinkedHashMap 多了 before 和 after 結構。

下面是Map類集合基本元素的實現演變。

圖片

LinkedHashMap 中 Entry 相對于 HashMap 多出的 before 和 after 便是用來維護 LinkedHashMap 插入 Entry 的先后順序的。

②、其它屬性

//用來指向雙向鏈表的頭節點
transient LinkedHashMap.Entry< K,V > head;
//用來指向雙向鏈表的尾節點
transient LinkedHashMap.Entry< K,V > tail;
//用來指定LinkedHashMap的迭代順序
//true 表示按照訪問順序,會把訪問過的元素放在鏈表后面,放置順序是訪問的順序
//false 表示按照插入順序遍歷
final boolean accessOrder;

注意:這里有五個屬性別搞混淆的,對于 Node next 屬性,是用來維護整個集合中 Entry 的順序。對于 Entry before,Entry after ,以及 Entry head,Entry tail,這四個屬性都是用來維護保證集合順序的鏈表,其中前兩個before和after表示某個節點的上一個節點和下一個節點,這是一個雙向鏈表。后兩個屬性 head 和 tail 分別表示這個鏈表的頭節點和尾節點。

3、構造函數

①、無參構造

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

調用無參的 HashMap 構造函數,具有默認初始容量(16)和加載因子(0.75)。并且設定了 accessOrder = false,表示默認按照插入順序進行遍歷。

②、指定初始容量

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

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

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

4、添加元素

LinkedHashMap 中是沒有 put 方法的,直接調用父類 HashMap 的 put 方法。關于 HashMap 的put 方法,可以參看我之前對于 HashMap 的介紹。

我將方法介紹復制到下面:

//hash(key)就是上面講的hash方法,對其進行了第一步和第二步處理
   public V put(K key, V value) {
       return putVal(hash(key), key, value, false, true);
   }
   /**
    *
    * @param hash 索引的位置
    * @param key  鍵
    * @param value  值
    * @param onlyIfAbsent true 表示不要更改現有值
    * @param evict false表示table處于創建模式
    * @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或者長度為0,則進行初始化
        //resize()方法本來是用于擴容,由于初始化沒有實際分配空間,這里用該方法進行空間分配,后面會詳細講解該方法
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        //注意:這里用到了前面講解獲得key的hash碼的第三步,取模運算,下面的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插入到計算的索引i位置
        else {//tab[i] 不為null,表示該位置已經有值了
            Node< K,V > e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;//節點key已經有值了,直接用新值覆蓋
            //該鏈是紅黑樹
            else if (p instanceof TreeNode)
                e = ((TreeNode< K,V >)p).putTreeVal(this, tab, hash, key, value);
            //該鏈是鏈表
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        //鏈表長度大于8,轉換成紅黑樹
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    //key已經存在直接覆蓋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)//超過最大容量,進行擴容
            resize();
        afterNodeInsertion(evict);
        return null;
   }

5、刪除元素

同理也是調用 HashMap 的remove 方法,這里我不作過多的講解,著重看LinkedHashMap 重寫的第 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;
        //如果鍵的值與鏈表第一個節點相等,則將 node 指向該節點
        if (p.hash == hash &&
        ((k = p.key) == key || (key != null && key.equals(k))))
        node = p;
        //如果桶節點存在下一個節點
        else if ((e = p.next) != null) {
            //節點為紅黑樹
        if (p instanceof TreeNode)
         node = ((TreeNode< K,V >)p).getTreeNode(hash, key);//找到需要刪除的紅黑樹節點
        else {
         do {//遍歷鏈表,找到待刪除的節點
             if (e.hash == hash &&
                 ((k = e.key) == key ||
                  (key != null && key.equals(k)))) {
                 node = e;
                 break;
             }
             p = e;
         } while ((e = e.next) != null);
        }
        }
        //刪除節點,并進行調節紅黑樹平衡
        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行代碼,當 accessOrder = true 時,即表示按照最近訪問的迭代順序,會將訪問過的元素放在鏈表后面。

對于 afterNodeAccess(e) 方法,在前面第 4 小節 添加元素已經介紹過了,這就不在介紹。

7、遍歷元素

在介紹 HashMap 時,我們介紹了 4 中遍歷方式,同理,對于 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、小結

好了,這就是JDK中java.util.LinkedHashMap 類的介紹。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據
    +關注

    關注

    8

    文章

    7085

    瀏覽量

    89214
  • 函數
    +關注

    關注

    3

    文章

    4338

    瀏覽量

    62762
  • MAP
    MAP
    +關注

    關注

    0

    文章

    49

    瀏覽量

    15151
  • 元素
    +關注

    關注

    0

    文章

    47

    瀏覽量

    8451
收藏 人收藏

    評論

    相關推薦

    【labview我來告訴你】實現任何LabVIEW數據類型集合的簡潔方式

    則是元素排列按一定順序的集合。Variant attributes 提供了一個非常好而簡潔的方式來實現任何 LabVIEW 數據類型的集合。 比如我們想創建一個字符串的有序
    發表于 12-30 09:30

    【labview我來告訴你】簡潔的實現任何 LabVIEW 數據類型的集合

    而簡潔的方式來實現任何 LabVIEW 數據類型的集合。 比如我們想創建一個字符串的有序集合,我們可以通過使用Set Variant Attribute 來追加新的元素迚去。作為 Va
    發表于 01-11 09:52

    簡潔的實現任何 LabVIEW 數據類型的集合

    而簡潔的方式來實現任何 LabVIEW 數據類型的集合。 比如我們想創建一個字符串的有序集合,我們可以通過使用Set Variant Attribute 來追加新的元素迚去。作為 Va
    發表于 12-17 09:51

    java集合干貨系列

    :List列表、Set集合、Map映射、工具(Iterator迭代器、Enumeration枚舉、Arrays和Collections)?! ollection接口、子接口以及
    發表于 12-14 15:11

    干貨!對 buck-boost 進行演變,最終會演變成 flyback

    演變成更復雜的拓撲結構,那么我們融會貫通的理解各種拓撲結構,就變得非常容易。其實理解隔離電源,相對非隔離DCDC來說,需要多理解一個基本元素——變壓器。然后很多基本原理也可以通過基本拓撲進行演變。本文
    發表于 01-12 16:09

    python入門知識:什么是set集合

    集合set set集合是一個無序不重復元素的集,基本功能包括關系測試和消除重復元素集合使用大括號({})框定
    發表于 09-24 16:29

    python集合

    python集合集合(英文名 set),它是一個無序的不重復元素序列。這里面有兩個重點:無序,不重復1. 創建集合集合的創建有兩種方法第一種方法:使用 花括號 {} 直接創建,創建的時候,{} 可以
    發表于 02-23 17:04

    HarmonyOS方舟開發框架容器API的介紹與使用

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

    JAVA集合匯總

    多數情況下使用。 二、層次關系 如圖所示:圖中,實線邊框的是實現,折線邊框的是抽象,而點線邊框的是接口 Collection 接口是集合
    的頭像 發表于 01-16 11:50 ?3796次閱讀
    JAVA<b class='flag-5'>集合</b><b class='flag-5'>類</b>匯總

    數組與集合說明

    對數組與集合進行詳細介紹。
    發表于 03-17 14:28 ?6次下載
    數組與<b class='flag-5'>集合</b><b class='flag-5'>類</b>說明

    什么是 map

    map 容器,又稱鍵值對容器,即該容器的底層是以紅黑樹變體實現的,是典型的關聯式容器。這意味著,map 容器中的元素可以分散存儲在內存空間里,而不是必須存儲在一整塊連續的內存空間中。跟
    的頭像 發表于 02-27 15:41 ?3022次閱讀

    python集合表達式及方法

    python數字的集合(set)類型,是無序集合,集合中的元素(項)不會重復,不管添加多少個相同元素(項),只會保存1次。
    的頭像 發表于 03-10 10:06 ?1363次閱讀

    Java8的Stream流 map() 方法

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

    List 轉 Map的方法

    在我們平時的工作中,充滿了各種類型之間的轉換。今天小編帶大家上手 List 轉 Map 的各種操作。 我們將假設 List 中的每個元素都有一個標識符,該標識符將在生成的 Map 中作為一個鍵
    的頭像 發表于 10-09 16:10 ?1656次閱讀

    LinkedHashSet 和 LinkedHashMap定義

    Map 集合實現了 Set 集合。 1、LinkedHashSet 定義 LinkedHa
    的頭像 發表于 10-10 15:10 ?511次閱讀
    LinkedHashSet 和 LinkedHashMap定義
    主站蜘蛛池模板: 果冻传媒2021一二三在线观看| 国产精品嫩草99AV在线| 性欧美videofree中文字幕| 日本bbwhd| 摸老师丝袜小内内摸出水| 擼擼擼麻豆密臀AV| 久久婷婷五月综合色精品首页 | 久久精品人人做人人爽97| 韩国电影久久| 狠狠色丁香久久婷婷综合_中 | 香蕉久久一区二区三区啪啪| 无码日本亚洲一区久久精品 | 国产免费看片| 国产视频精品在线偷拍| 国产亚洲综合视频| 好男人在线视频| 久久re亚洲在线视频| 久久婷婷五月综合色丁香花| 蜜臀AV人妻久久无码精品麻豆| 免费看到湿的小黄文软件APP | 亚洲精品嫩草研究院久久| 亚洲字幕在线观看| 在线欧美 精品 第1页| 2017日日干| 99热婷婷国产精品综合| yellow日本动漫免费观看| 高h肉文合集| 国产亚洲精品久久久999无毒| 国产精人妻无码一区麻豆| 精品视频一区二区三三区四区| 精品少妇高潮蜜臀涩涩AV| 日本人吃奶玩奶虐乳| 色偷偷7777www| 天天操天天干天天爽| 无码不卡中文字幕在线观看| 亚洲精品久久久久久久蜜臀老牛 | XXOO麻豆国产在线九九爱| 动漫女主被扒开双腿羞辱| 国产三级在线观看视频| 久久re视频这里精品免费1| 女厕所边摸边吃奶边做爽视频|