1. 程式人生 > >Java集合(四):TreeMap原始碼解析

Java集合(四):TreeMap原始碼解析

前言

今天來介紹下TreeMap,TreeMap是基於紅黑樹結構實現的一種Map,要分析TreeMap的實現首先就要對紅黑樹有所瞭解。
構造圖如下:
藍色線條:繼承
綠色線條:介面實現

正文

TreeMap底層是基於紅黑樹(Red-Black tree)實現,所以在學習TreeMap之前我們先來了解下紅黑樹。
紅黑樹又稱紅-黑二叉樹,它首先是一顆二叉樹,它具體二叉樹所有的特性。同時紅黑樹更是一顆自平衡的排序二叉樹。
我們知道一顆基本的二叉樹他們都需要滿足一個基本性質–即樹中的任何節點的值大於它的左子節點,且小於它的右子節點。按照這個基本性質使得樹的檢索效率大大提高。我們知道在生成二叉樹的過程是非常容易失衡的,最壞的情況就是一邊倒(只有右/左子樹),這樣勢必會導致二叉樹的檢索效率大大降低(O(n)),所以為了維持二叉樹的平衡,大牛們提出了各種實現的演算法,如:

AVLSBT伸展樹TREAP ,紅黑樹等等。

平衡二叉樹必須具備如下特性:它是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹。也就是說該二叉樹的任何一個等等子節點,其左右子樹的高度都相近。

紅黑樹顧名思義就是節點是紅色或者黑色的平衡二叉樹,它通過顏色的約束來維持著二叉樹的平衡。對於一棵有效的紅黑樹二叉樹而言我們必須增加如下規則:

  1. 每個節點都只能是紅色或者黑色
  2. 根節點是黑色
  3. 每個葉節點(NIL節點,空節點)是黑色的。
  4. 如果一個結點是紅的,則它兩個子節點都是黑的。也就是說在一條路徑上不能出現相鄰的兩個紅色結點。
  5. 從任一節點到其每個葉子的所有路徑都包含相同數目的黑色節點。

紅黑樹示意圖如下:

上面的規則前4條都好理解,第5條規則到底是什麼情況,下面簡單解釋下,比如圖中紅8到1左邊的葉子節點的路徑包含兩個黑色節點,到6下面的葉子節點的路徑也包含兩個黑色節點。

但是在在新增或刪除節點後,紅黑樹就發生了變化,可能不再滿足上面的5個特性,為了保持紅黑樹的以上特性,就有了三個動作:左旋、右旋、著色。

下面來看下什麼是紅黑樹的左旋和右旋:

對x進行左旋,意味著”將x變成一個左節點”

對y進行右旋,意味著”將y變成一個右節點”。
如果還是沒看明白,下面找了兩張左旋和右旋的動態圖


ok,對二叉樹、紅黑樹的概念有所瞭解後,我們來看下紅黑樹的兩個主要邏輯新增和刪除,看看TreeMap是怎麼實現的。

TreeMap簡介

TreeMap定義

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

TreeMap 是一個有序的key-value集合,它是通過紅黑樹實現的。
TreeMap 繼承於AbstractMap,所以它是一個Map,即一個key-value集合。
TreeMap 實現了NavigableMap介面,意味著它支援一系列的導航方法。比如返回有序的key集合。
TreeMap 實現了Cloneable介面,意味著它能被克隆
TreeMap 實現了java.io.Serializable介面,意味著它支援序列化

TreeMap基於紅黑樹(Red-Black tree)實現。該對映根據其鍵的自然順序進行排序,或者根據建立對映時提供的 Comparator 進行排序,具體取決於使用的構造方法。
TreeMap的基本操作 containsKey、get、put 和 remove 的時間複雜度是 log(n) 。
另外,TreeMap是非同步的。 它的iterator 方法返回的迭代器是fail-fast的。

TreeMap屬性

1
2
3
4
5
6
7
8
9
10
11
// 比較器
private final Comparator<? super K> comparator;

// 紅黑樹根節點
private transient Entry<K,V> root = null;

// 集合元素數量
private transient int size = 0;

// "fail-fast"集合修改記錄
private transient int modCount = 0;

TreeMap的本質是R-B Tree(紅黑樹),它包含幾個重要的成員變數: root, size, comparator。

  • root 是紅黑數的根節點。它是Entry型別,Entry是紅黑數的節點,它包含了紅黑數的6個基本組成成分:key(鍵)、value(值)、left(左孩子)、right(右孩子)、parent(父節點)、color(顏色)。Entry節點根據key進行排序,Entry節點包含的內容為value。
  • 紅黑數排序時,根據Entry中的key進行排序;Entry中的key比較大小是根據比較器comparator來進行判斷的。
  • size是紅黑數中節點的個數。

Entry是樹的節點類,我們來看一下Entry的定義:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
static final class Entry<K,V> implements Map.Entry<K,V> {
       K key;
        V value;
        // 左孩子節點
        Entry<K,V> left = null;
        // 右孩子節點
        Entry<K,V> right = null;
        // 父節點
        Entry<K,V> parent;
        // 紅黑樹用來表示節點顏色的屬性,預設為黑色
        boolean color = BLACK;

        /**
         * 用key,value和父節點構造一個Entry,預設為黑色
         */
        Entry(K key, V value, Entry<K,V> parent) {
            this.key = key;
            this.value = value;
            this.parent = parent;
        }

        public K getKey() {
            return key ;
        }

        public V getValue() {
            return value ;
        }

        public V setValue(V value) {
            V oldValue = this.value ;
            this.value = value;
            return oldValue;
        }

        public boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;

            return valEquals( key,e.getKey()) && valEquals( value,e.getValue());
        }

        public int hashCode() {
            int keyHash = (key ==null ? 0 : key.hashCode());
            int valueHash = (value ==null ? 0 : value.hashCode());
            return keyHash ^ valueHash;
        }

        public String toString() {
            return key + "=" + value;
        }
    }

Entry類理解起來比較簡單(因為我們前面看過很多的Entry類了),主要是定義了樹的孩子和父親節點引用,和紅黑顏色屬性,並對equals和hashCode進行重寫,以利於比較是否相等。

HashMap建構函式

相關推薦

Java集合TreeMap原始碼解析

前言今天來介紹下TreeMap,TreeMap是基於紅黑樹結構實現的一種Map,要分析TreeMap的實現首先就要對紅黑樹有所瞭解。構造圖如下:藍色線條:繼承綠色線條:介面實現正文TreeMap底層是基於紅黑樹(Red-Black tree)實現,所以在學習TreeMap之前

java集合6TreeMap原始碼分析jdk1.8

前言 TreeMap的基本概念: TreeMap集合是基於紅黑樹(Red-Black tree)的 NavigableMap實現。該集合最重要的特點就是可排序,該對映根據其鍵的自然順序進行排序,或者根據建立對映時提供的 Comparator 進行排序,具體

Java集合ArrayList原始碼解析

前言今天來介紹下ArrayList,在集合框架整體框架一章中,我們介紹了List介面,ArrayList繼承了AbstractList,實現了List。ArrayList在工作中經常用到,所以要弄懂這個類是極其重要的。構造圖如下:藍色線條:繼承綠色線條:介面實現正文Array

java集合4HashMap原始碼分析jdk1.8

前言 Map介面雖然也是集合體系中的重要一個分支,但是Map介面並不繼承自Collection,而是自成一派。 public interface Map<K,V> Map集合儲存鍵對映到值的物件。一個集合中不能包含重複的鍵,每個鍵最多

java集合5HashSet原始碼分析

前言 HashSet實現 Set 介面,由雜湊表(實際上是一個 HashMap 例項)支援。它不保證 set的迭代順序;特別是它不保證該順序恆久不變。此類允許使用 null 元素。Set集合取出元素

java集合7TreeSet原始碼分析jdk1.8

前言 TreeSet是基於 TreeMap 的 NavigableSet 實現。使用元素的自然順序對元素進行排序,或者根據建立 set 時提供的 Comparator 進行排序,具體取決於使用的構造方法。這句話什麼意思呢?就是說,跟HashSet底層是一個Ha

大資料之JAVA基礎集合ArrayList

1.集合的建立1).ArrayList集合看作一個長度可變的陣列2).ArrayList<要儲存元素的資料型別> 變數名 = new ArrayList<要儲存元素的資料型別>();3).集合中儲存的元素,只能為<>括號中指定的資料型別元素

Java-MavenEclipse集成Maven環境配置

查找 epo 情況 jpg ont 使用 eclipse版 需要 style 一般maven都需要集成到IDE上使用的,而不是單獨的使用,常見的maven可集成IDE:eclipse、IntelliJ IDEA。但這裏就只學習eclipse集成maven的基礎上,進行mav

java集合List、Iterator、Array、ArrayList、LinkList

整體 http 是否 簡潔 畢業 一個 位置 數據 reac 畢業這麽久,java 標準庫中的集合都沒怎麽仔細了解過,準備好好學習學習。 集合(Collection):由一個或多個確定的元素所構成的整體叫做 集合--百度百科的解釋。換言之,就是裝元素的容器,元素可以是任何類

Java併發volatile的實現原理 Java併發Java記憶體模型乾貨總結

synchronized是一個重量級的鎖,volatile通常被比喻成輕量級的synchronized volatile是一個變數修飾符,只能用來修飾變數。 volatile寫:當寫一個volatile變數時,JMM會把該執行緒對應的本地記憶體中的共享變數重新整理到主記憶體。 volatile讀:當讀一

Java併發happens-before

happens-before 一個操作執行的結果需要對另一個操作可見,那麼這兩個操作之間必須存在happens-before關係 happen-before原則是JMM中非常重要的原則,它是判斷資料是否存在競爭、執行緒是否安全的主要依據,保證了多執行緒環境下的可見性。 happens-before原則定

【第17天】Java集合---Sorted介面實現的TreeSet集合及單值型別集合總結

1 TreeSet簡介 2 基本用法與特點 3 制定單值比較規則 3.1 自然排序(compareTo(Object obj)) 3.2 定製排序(定義比較器類) 3.2.1 普通類內定義

Java併發volatile的實現原理

synchronized是一個重量級的鎖,volatile通常被比喻成輕量級的synchronized volatile是一個變數修飾符,只能用來修飾變數。 volatile寫:當寫一個volatile變數時,JMM會把該執行緒對應的本地記憶體中的共享變數重新整理到主記憶體。 volatile讀:當讀一個vo

Java容器HashMapJava 7的實現原理

一、HashMap的定義和建構函式 public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, S

java基礎字串

1.String概念:字串一旦被建立就不可以更改 (1)A.==B:判斷地址;     A.equals(B):判斷A,B的內容 (2).常用方法:         長度:str.length();  

Java入門運算子優先順序、關鍵字與保留字

上次介紹了Java的運算子,今天來介紹下運算子的優先順序,以及Java的關鍵字、保留字。 一、運算子優先順序 序號 運算子 名稱 目數 結合性 說明 1 [ ]

Java集合HashMap詳解

HashMap簡介 java.lang.Object ↳ java.util.AbstractMap<K, V> ↳ java.util.HashMap<K, V> public class HashMap<K,V> ex

java程式碼構建Document

這裡的示例程式碼都是簡要程式碼,詳細程式碼可以參考我打包好的程式碼,地址:百度雲 mongo-demo.rar 構建Document Document document = new Do

ORBSLAM2學習DBoW2原始碼分析OrbVocabulary部分

{(w1,weight1),(w2,weight2),...,(wn,weightn)}的形式,就對應著這裡的BowVector。BowVector派生自public std::map<WordId, WordValue>,實際上就是public std::map<int, double&g

java集合1java中的集合簡介

一、java資料結構的簡介 java中包含了很多常用的資料結構,如陣列、連結串列、棧、佇列、集合、雜湊表等,Java集合工具包位於Java.util包下。Java集合框架下大致可以分為如下五個部分:List列表、Set集合、Map對映、迭代器(Iterator、Enumer