extends AbstractMap K , V > implements NavigableMap K , V >, Cloneable , java.io.Serializable TreeMap 首先繼承了 AbstractMap 抽象類,表示它具有散列表的性質,也就是由 key-value 組成。 其次 TreeMap 實現了 NavigableMap 接口,該" />

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

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

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

3天內不再提示

JDK中java.util.TreeMap 類的介紹

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

本篇文章給大家介紹基于樹實現的數據結構——TreeMap

1、TreeMap 定義

聽名字就知道,TreeMap 是由Tree 和 Map 集合有關的,沒錯,TreeMap 是由紅黑樹實現的有序的 key-value 集合。

PS:想要學懂TreeMap的實現原理,紅黑樹的了解是必不可少的!!!

public class TreeMap< K,V >
    extends AbstractMap< K,V >
    implements NavigableMap< K,V >, Cloneable, java.io.Serializable

圖片

TreeMap 首先繼承了 AbstractMap 抽象類,表示它具有散列表的性質,也就是由 key-value 組成。

其次 TreeMap 實現了 NavigableMap 接口,該接口支持一系列獲取指定集合的導航方法,比如獲取小于指定key的集合。

最后分別實現 Serializable 接口以及 Cloneable 接口,分別表示支持對象序列化以及對象克隆。

2、字段定義

①、Comparator

/**
     * The comparator used to maintain order in this tree map, or
     * null if it uses the natural ordering of its keys.
     *
     * @serial
     */
    private final Comparator< ? super K > comparator;

可以看上面的英文注釋,Comparator 是用來維護treemap集合中的順序,如果為null,則按照key的自然順序。

Comparator 是一個接口,排序時需要實現其 compare 方法,該方法返回正數,零,負數分別代表大于,等于,小于。那么怎么使用呢?這里舉個例子:

這里有一個Person類,里面有兩個屬性pname,page,我們將該person對象放入ArrayList集合時,需要對其按照年齡進行排序。

package com.ys.test;

/**
 * Create by YSOcean
 */
public class Person {
    private String pname;
    private Integer page;

    public Person() {
    }

    public Person(String pname, Integer page) {
        this.pname = pname;
        this.page = page;
    }

    public String getPname() {
        return pname;
    }

    public void setPname(String pname) {
        this.pname = pname;
    }

    public Integer getPage() {
        return page;
    }

    public void setPage(Integer page) {
        this.page = page;
    }

    @Override
    public String toString() {
        return "Person{" +
                "pname='" + pname + ''' +
                ", page=" + page +
                '}';
    }
}

打印結果為:

圖片

②、Entry

private transient Entry< K,V > root;

對于Entry詳細源碼這里不列舉了,主要看幾個字段:

K key;
V value;
Entry K,V > left;
Entry K,V > right;
Entry K,V > parent;
boolean color = BLACK;

相信對紅黑樹這種數據結構了解的人,一看這幾個字段就明白了,這也印證了前面所說的TreeMap底層有紅黑樹這種數據結構。

③、size

/**
     * The number of entries in the tree
     */
    private transient int size = 0;

用來表示entry的個數,也就是key-value的個數。

④、modCount

/**
     * The number of structural modifications to the tree.
     */
    private transient int modCount = 0;

基本上前面講的在ArrayList,LinkedList,HashMap等線程不安全的集合都有此字段,用來實現Fail-Fast 機制,如果在迭代這些集合的過程中,有其他線程修改了這些集合,就會拋出ConcurrentModificationException異常。

⑤、紅黑樹常量

private static final boolean RED   = false;
    private static final boolean BLACK = true;

3、構造函數

①、無參構造函數

1     public TreeMap() {
2         comparator = null;
3     }

比較器 comparator 置為 null,表示按照key的自然順序進行排序。

②、帶比較器的構造函數

1     public TreeMap(Comparator< ? super K > comparator) {
2         this.comparator = comparator;
3     }

需要自己實現Comparator。

③、構造包含指定map集合的元素

1     public TreeMap(Map< ? extends K, ? extends V > m) {
2         comparator = null;
3         putAll(m);
4     }

使用該構造器創建的TreeMap,會默認插入m表示的集合元素,并且comparator表示按照自然順序進行插入。

④、帶 SortedMap的構造函數

public TreeMap(SortedMap< K, ? extends V > m) {
        comparator = m.comparator();
        try {
            buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
        } catch (java.io.IOException cannotHappen) {
        } catch (ClassNotFoundException cannotHappen) {
        }
    }

和上面帶Map的構造函數不一樣,map是無序的,而SortedMap 是有序的,使用 buildFromSorted() 方法將SortedMap集合中的元素插入到TreeMap 中。

4、添加元素

//添加元素
    public V put(K key, V value) {
        TreeMap.Entry< K,V > t = root;
        //如果根節點為空,即TreeMap中一個元素都沒有,那么設置新添加的元素為根節點
        //并且設置集合大小size=1,以及modCount+1,這是用于快速失敗
        if (t == null) {
            compare(key, key); // type (and possibly null) check

            root = new TreeMap.Entry<  >(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
        int cmp;
        TreeMap.Entry< K,V > parent;
        // split comparator and comparable paths
        Comparator< ? super K > cpr = comparator;
        //如果比較器不為空,即初始化TreeMap構造函數時,有傳遞comparator類
        //那么插入新的元素時,按照comparator實現的類進行排序
        if (cpr != null) {
            //通過do-while循環不斷遍歷樹,調用比較器對key值進行比較
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    //遇到key相等,直接將新值覆蓋到原值上
                    return t.setValue(value);
            } while (t != null);
        }
        //如果比較器為空,即初始化TreeMap構造函數時,沒有傳遞comparator類
        //那么插入新的元素時,按照key的自然順序
        else {
            //如果key==null,直接拋出異常
            //注意,上面構造TreeMap傳入了Comparator,是可以允許key==null
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
            Comparable< ? super K > k = (Comparable< ? super K >) key;
            do {
                parent = t;
                cmp = k.compareTo(t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        //找到父親節點,根據父親節點創建一個新節點
        TreeMap.Entry< K,V > e = new TreeMap.Entry<  >(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        //修正紅黑樹(包括節點的左旋和右旋,具體可以看我Java數據結構和算法中對紅黑樹的介紹)
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }

添加元素,如果初始化TreeMap構造函數時,沒有傳遞comparator類,是不允許插入key==null的鍵值對的,相反,如果實現了Comparator,則可以傳遞key=null的鍵值對。

另外,當插入一個新的元素后(除了根節點),會對TreeMap數據結構進行修正,也就是對紅黑樹進行修正,使其滿足紅黑樹的幾個特點,具體修正方法包括改變節點顏色,左旋,右旋等操作,這里我不做詳細介紹了.

5、刪除元素

①、根據key刪除

public V remove(Object key) {
        //根據key找到該節點
        TreeMap.Entry< K,V > p = getEntry(key);
        if (p == null)
            return null;
        //獲取該節點的value,并返回
        V oldValue = p.value;
        //調用deleteEntry()方法刪除節點
        deleteEntry(p);
        return oldValue;
    }

    private void deleteEntry(TreeMap.Entry< K,V > p) {
        modCount++;
        size--;

        //如果刪除節點的左右節點都不為空,即有兩個孩子
        if (p.left != null && p.right != null) {
            //得到該節點的中序后繼節點
            TreeMap.Entry< K,V > s = successor(p);
            p.key = s.key;
            p.value = s.value;
            p = s;
        } // p has 2 children

        // Start fixup at replacement node, if it exists.
        TreeMap.Entry< K,V > replacement = (p.left != null ? p.left : p.right);
        //待刪除節點只有一個子節點,直接刪除該節點,并用該節點的唯一子節點頂替該節點
        if (replacement != null) {
            // Link replacement to parent
            replacement.parent = p.parent;
            if (p.parent == null)
                root = replacement;
            else if (p == p.parent.left)
                p.parent.left  = replacement;
            else
                p.parent.right = replacement;

            // Null out links so they are OK to use by fixAfterDeletion.
            p.left = p.right = p.parent = null;

            // Fix replacement
            if (p.color == BLACK)
                fixAfterDeletion(replacement);

            //TreeMap中只有待刪除節點P,也就是只有一個節點,直接返回nul即可
        } else if (p.parent == null) { // return if we are the only node.
            root = null;
        } else { //  No children. Use self as phantom replacement and unlink.
            //待刪除節點沒有子節點,即為葉子節點,直接刪除即可
            if (p.color == BLACK)
                fixAfterDeletion(p);

            if (p.parent != null) {
                if (p == p.parent.left)
                    p.parent.left = null;
                else if (p == p.parent.right)
                    p.parent.right = null;
                p.parent = null;
            }
        }
    }

刪除節點分為四種情況:

1、根據key沒有找到該節點:也就是集合中不存在這一個節點,直接返回null即可。

2、根據key找到節點,又分為三種情況:

①、待刪除節點沒有子節點,即為葉子節點:直接刪除該節點即可。

②、待刪除節點只有一個子節點:那么首先找到待刪除節點的子節點,然后刪除該節點,用其唯一子節點頂替該節點。

③、待刪除節點有兩個子節點:首先找到該節點的中序后繼節點,然后把這個后繼節點的內容復制給待刪除節點,然后刪除該中序后繼節點,刪除過程又轉換成前面①、②兩種情況了,這里主要是找到中序后繼節點,相當于待刪除節點的一個替身。

6、查找元素

①、根據key查找

public V get(Object key) {
        TreeMap.Entry< K,V > p = getEntry(key);
        return (p==null ? null : p.value);
    }

    final TreeMap.Entry< K,V > getEntry(Object key) {
        // Offload comparator-based version for sake of performance
        if (comparator != null)
            return getEntryUsingComparator(key);
        if (key == null)
            throw new NullPointerException();
        @SuppressWarnings("unchecked")
        Comparable< ? super K > k = (Comparable< ? super K >) key;
        TreeMap.Entry< K,V > p = root;
        while (p != null) {
            int cmp = k.compareTo(p.key);
            if (cmp < 0)
                p = p.left;
            else if (cmp > 0)
                p = p.right;
            else
                return p;
        }
        return null;
    }

7、遍歷元素

通常有下面兩種方法,第二種方法效率要快很多。

TreeMap< String,Integer > map = new TreeMap<  >();
map.put("A",1);
map.put("B",2);
map.put("C",3);

//第一種方法
//首先利用keySet()方法得到key的集合,然后利用map.get()方法根據key得到value
Iterator< String > iterator = map.keySet().iterator();
while(iterator.hasNext()){
    String key = iterator.next();
    System.out.println(key+":"+map.get(key));
}

//第二種方法
Iterator< Map.Entry< String,Integer >> iterator1 = map.entrySet().iterator();
while(iterator1.hasNext()){
    Map.Entry< String,Integer > entry = iterator1.next();
    System.out.println(entry.getKey()+":"+entry.getValue());
}

8、小結

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

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

    關注

    19

    文章

    2974

    瀏覽量

    104980
  • MAP
    MAP
    +關注

    關注

    0

    文章

    49

    瀏覽量

    15164
  • 數據結構
    +關注

    關注

    3

    文章

    573

    瀏覽量

    40195
  • JDK
    JDK
    +關注

    關注

    0

    文章

    82

    瀏覽量

    16619
收藏 人收藏

    評論

    相關推薦

    java jdk安裝參考步驟

    1、把jdk-8u5-linux-x64.gz解壓,然后把解壓的文件夾放到/usr/lib/jvm/下,并重命名為jdk,這個目錄可以自定義。2、編輯~/.basrc文件,在文件的末尾追加下面的命令
    發表于 09-25 16:43

    樹莓派如何安裝Java JDK

    。Oracle Java 具有其他一些商業功能,并且許可僅允許非商業用途。下面介紹如何在樹莓派的 Raspbian OS 上安裝Java(OpenJDK)。  運行以下命令安裝最新的 JDK
    發表于 02-02 16:37

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

    對外提供。通過對存儲位置以及屬性的限制,讓每種類型的數據都能在完成自身功能的基礎上剪除冗余分支,保證了數據的高效訪問,提升了應用的性能。 本期,我們將為大家介紹方舟開發框架容器的各種類型以及相關
    發表于 03-07 11:40

    看看基于JDK自帶JVM工具的用法

    用到命令,下面圍繞一個微服務的啟動和運行,來看看基于JDK自帶JVM工具的用法;三、命令行工具1、jps命令jps :虛擬機進程狀態工具,該命令在Java環境部署和服務啟動查看時經常用到,首先在本地
    發表于 11-16 15:30

    java jdk6.0官方下載

    java jdk6.0下載如何件: java jdk6.0安裝步驟: 第一步 JDK1.6的安裝步驟 第一步雙擊安裝文件
    發表于 10-17 11:47 ?155次下載
    <b class='flag-5'>java</b> <b class='flag-5'>jdk</b>6.0官方下載

    java基礎——java.util.ConcurrentModificationException

    本文檔內容介紹java基礎java.util.ConcurrentModificationException,供參考
    發表于 03-13 11:31 ?2次下載

    JavaArrays是什么 Arrays常用方法

    了解Arrays的概念 **A****rrays** 位于java.util包下,Arrays是一個操作數組的工具。 Arrays常用方法 Arrays.fill:
    的頭像 發表于 02-17 15:11 ?1081次閱讀
    <b class='flag-5'>Java</b><b class='flag-5'>中</b>Arrays<b class='flag-5'>類</b>是什么 Arrays常用方法

    JDKjava.util.HashSet 介紹

    JDK1.8 ,HashMap 是由 數組+鏈表+紅黑樹構成,相對于早期版本的 JDK HashMap 實現,新增了紅黑樹作為底層數據結構,在數據量較大且哈希碰撞較多時,能夠極大的增加檢索
    的頭像 發表于 10-09 10:50 ?637次閱讀
    <b class='flag-5'>JDK</b><b class='flag-5'>中</b><b class='flag-5'>java.util</b>.HashSet <b class='flag-5'>類</b>的<b class='flag-5'>介紹</b>

    Java時間轉換方案

    LocalDate 的過程,我們使用 Date Java 8 新增的 toInstant() 方法進行轉換。 當我們轉換一個 Instant 對象時,需要使用 ZoneId
    的頭像 發表于 10-09 15:48 ?517次閱讀

    JDKjava.util.ArrayList 介紹

    AbstractList E > implements List E >, RandomAccess , Cloneable , java.io.Serializable ①、實現 RandomAccess 接口 這是
    的頭像 發表于 10-10 15:51 ?719次閱讀
    <b class='flag-5'>JDK</b><b class='flag-5'>中</b><b class='flag-5'>java.util</b>.ArrayList <b class='flag-5'>類</b>的<b class='flag-5'>介紹</b>

    JDKjava.lang.Arrays 的源碼解析

    日常開發,我們會使用各種工具,利用封裝好的輪子,能讓我們的開發事半功倍。但是在JDK,有一個特別的工具——
    的頭像 發表于 10-11 15:31 ?656次閱讀
    <b class='flag-5'>JDK</b><b class='flag-5'>中</b><b class='flag-5'>java</b>.lang.Arrays <b class='flag-5'>類</b>的源碼解析

    javautil包下有哪些

    Javautil包下,包含了許多,用于提供各種常見的實用工具和數據結構。以下是一些常見的: ArrayList:動態數組,可以根據需要自動調整大小。 LinkedList:雙向
    的頭像 發表于 11-22 15:04 ?1188次閱讀

    weblogic修改jdk路徑

    )路徑的情況。本文將詳細介紹如何在WebLogic修改JDK路徑。 一、背景介紹 Java Development Kit(
    的頭像 發表于 12-05 14:46 ?1365次閱讀

    OpenHarmony語言基礎庫【@ohos.util.TreeMap (非線性容器TreeMap)】

    TreeMap可用于存儲具有關聯關系的key-value鍵值對集合,存儲元素key值唯一,每個key對應一個value。
    的頭像 發表于 04-28 15:23 ?317次閱讀
    OpenHarmony語言基礎<b class='flag-5'>類</b>庫【@ohos.<b class='flag-5'>util.TreeMap</b> (非線性容器<b class='flag-5'>TreeMap</b>)】

    Java集合API的改進介紹

    簡介 本文我們將探討不同 jdk 版本各類的起源,以及新引入的和接口背后的目的。我們將分析之前版本存在的問題,以及為何需要引入新的或接口。此外,我們還將
    的頭像 發表于 11-22 11:12 ?246次閱讀
    <b class='flag-5'>Java</b>集合API的改進<b class='flag-5'>介紹</b>
    主站蜘蛛池模板: 首页_亚洲AV色老汉影院 | 国内精品视频在线播放一区 | 肉色欧美久久久久久久蜜桃 | 校园刺激全黄H全肉细节文 校园纯肉H教室第一次 | 国产精品久久人妻拍拍水牛影视 | 99久久国产宗和精品1上映 | 国产精品嫩草免费视频 | 97国产蝌蚪视频在线观看 | 日日碰狠狠添天天爽 | 日日噜噜夜夜躁躁狠狠 | 国产精品免费大片一区二区 | 欧美高清vivoesond在线播放 | 亚洲国产欧美日韩在线一区 | 亚洲精品一区国产欧美 | 日韩人妻无码精品-专区 | 中文字幕在线免费视频 | 99婷婷久久精品国产一区二区 | 抽插性奴中出乳精内射 | 在线观看免费av网 | 97在线视频免费播放 | 亚在线观看免费视频入口 | 久久久精品免费视频 | 国产最猛性XXXX69交 | 在线观看视频一区 | 亚洲青青草原 | 在线免费观看亚洲视频 | 9966在线观看免费高清电影 | 成年人视频在线免费播放 | 人妻 中文无码 中出 | 久久精品18| 无码毛片内射白浆视频 | 花季v3.0.2黄在线观看 | 国产成人综合在线观看 | 国产在线AV一区二区香蕉 | 欧美高跟镣铐bdsm视频 | 寂寞夜晚视频在线观看 | 国产成人免费手机在线观看视频 | 久久精品国产亚洲AV天美18 | 精品国产乱码久久久久久夜深人妻 | 日本一区精品久久久久影院 | 狠狠人妻久久久久久综合九色 |