源碼的魅力 - TreeMap 的工作原理

源碼的魅力 - TreeMap 的工作原理(Android 7.1源碼)

簡介

由于HashMap與linkedHashMap都不能按照key的數(shù)據(jù)順序進行遍歷,所以后來就有了TreeMap。

怎么做到按照插入順序排序的呢

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

    public V put(K key, V value) {
        TreeMapEntry<K,V> t = root;
        if (t == null) {
            if (comparator != null) {
                if (key == null) {
                    comparator.compare(key, key);
                }
            } else {
                if (key == null) {
                    throw new NullPointerException("key == null");
                } else if (!(key instanceof Comparable)) {
                    throw new ClassCastException(
                            "Cannot cast" + key.getClass().getName() + " to Comparable.");
                }
            }

            root = new TreeMapEntry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
        int cmp;
        TreeMapEntry<K,V> parent;
        // split comparator and comparable paths
        Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        else {
            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);
        }
        TreeMapEntry<K,V> e = new TreeMapEntry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }

TreeMap存在一個參數(shù)為Comparator的構(gòu)造函數(shù)抠璃,在插入數(shù)據(jù)時默認是使用數(shù)據(jù)的默認比較器泌辫,否則使用比較器很钓,通過比較器比較的值挨队,如果相等則直接替換狈茉,如果不同則插入嘁字,使用紅黑樹維護整個結(jié)構(gòu)昨稼。

怎么獲取數(shù)據(jù)時是有序的呢

    abstract class PrivateEntryIterator<T> implements Iterator<T> {
        TreeMapEntry<K,V> next;
        TreeMapEntry<K,V> lastReturned;
        ...

        final TreeMapEntry<K,V> nextEntry() {
            TreeMapEntry<K,V> e = next;
            if (e == null)
                throw new NoSuchElementException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            next = successor(e);
            lastReturned = e;
            return e;
        }
    }

    //中序遍歷查找下一個節(jié)點
    static <K,V> TreeMapEntry<K,V> successor(TreeMapEntry<K,V> t) {
        if (t == null)
            return null;
        else if (t.right != null) {
            TreeMapEntry<K,V> p = t.right;
            while (p.left != null)
                p = p.left;
            return p;
        } else {
            TreeMapEntry<K,V> p = t.parent;
            TreeMapEntry<K,V> ch = t;
            while (p != null && ch == p.right) {
                ch = p;
                p = p.parent;
            }
            return p;
        }
    }

通過PrivateEntryIterator遍歷器然后,通過中序遍歷返回數(shù)據(jù)拳锚,正是排序的數(shù)據(jù)假栓。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市霍掺,隨后出現(xiàn)的幾起案子匾荆,更是在濱河造成了極大的恐慌拌蜘,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牙丽,死亡現(xiàn)場離奇詭異简卧,居然都是意外死亡,警方通過查閱死者的電腦和手機烤芦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門举娩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人构罗,你說我怎么就攤上這事铜涉。” “怎么了遂唧?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵芙代,是天一觀的道長。 經(jīng)常有香客問我盖彭,道長纹烹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任召边,我火速辦了婚禮铺呵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘隧熙。我一直安慰自己片挂,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布贱鼻。 她就那樣靜靜地躺著宴卖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪邻悬。 梳的紋絲不亂的頭發(fā)上症昏,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音父丰,去河邊找鬼肝谭。 笑死,一個胖子當(dāng)著我的面吹牛蛾扇,可吹牛的內(nèi)容都是我干的攘烛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼镀首,長吁一口氣:“原來是場噩夢啊……” “哼坟漱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起更哄,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤芋齿,失蹤者是張志新(化名)和其女友劉穎腥寇,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體觅捆,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡赦役,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了栅炒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掂摔。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖赢赊,靈堂內(nèi)的尸體忽然破棺而出乙漓,到底是詐尸還是另有隱情,我是刑警寧澤域携,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布簇秒,位于F島的核電站鱼喉,受9級特大地震影響秀鞭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扛禽,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一锋边、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧编曼,春花似錦豆巨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至熊户,卻和暖如春萍膛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嚷堡。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工蝗罗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蝌戒。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓串塑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親北苟。 傳聞我的和親對象是個殘疾皇子桩匪,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容