TreeMap的源碼學習

TreeMap的源碼學習java

一)、TreeMap的特色算法

根據key值進行排序。數據結構

二)、按key值排序的兩種排序算法實現ide

1).在構造方法中傳入比較器性能

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

   比較器comparator實現Comparator接口,實現compare(T o1, T o2)方法;

int compare(T o1, T o2);

2).key值實現Comparable接口,重寫 compareTo(key k)方法學習

T implements Comparable<T>{
    @override
    public int compareTo(T k)
}

注: 對於TreeMap而言,排序是一個必須進行的過程,要正常使用TreeMap必須制 定排序規則,加入Comparator或key對象實現Comparable接口,若沒有制定 比較規則則會拋出java.lang.ClassCastException。this

由於String對象默認實現了Comparable接口,實現了comparaTo方法,使用String類型做爲key值,不用進行排序。code

三)、TreeMap的數據結構orm

紅黑樹:Entry<k, v>對象

Entry<k ,v> 對象的屬性:

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

紅黑樹是一種平衡查找樹.

四)、TreeMap的主要屬性

//比較器
private final Comparator<? super K> comparator;
//樹的根節點
private transient Entry<K,V> root;
//節點個數即元素個數
private transient int size = 0;
//修改次數
private transient int modCount = 0;
//用於構造紅黑樹
private static final boolean RED   = false;
private static final boolean BLACK = true;

五)、TreeMap的put(K key, V value)方法

步驟:

1).獲取root節點,判斷是否第一次添加元素 ,如果第一次添加元素則將該元素設爲根節點。

2).如若不是第一次添加,根據key值,調用比較規則從根節點開始比較左右子樹直至到達葉子節點,根據key的比較結果決定放置到葉子節點的左樹位置或右樹位置,> 0放置右樹, < 0 放置右樹。

3).fixAfterInsertion修改插入元素後樹的結構,轉爲紅黑樹。

TreeMap<String, String> treeMap = new TreeMap<>();
        treeMap.put("a","v");

public V put(K key, V value) {
        //獲取根節點
        Entry<K,V> t = root;
        //若根節點爲空,直接將元素設爲樹的根節點,不用遍歷左右子樹
        if (t == null) {
            compare(key, key); // type (and possibly null) check
            //將元素設爲樹的根節點
            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
        //根據排序規則將元素插入到樹結構中
        int cmp;
        Entry<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);
        }
       //使用key 實現Comparable的compareTo()規則
        else {
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
                /**
                  若是Key沒有加入比較器或沒有實現Comparable這裏就
                  拋出java.lang,ClassCastException
                  */
                Comparable<? super K> k = (Comparable<? super K>) key;
            //一直比較左右子樹的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);
        }
         //根據返回的比較結果決定插入節點的位置
        Entry<K,V> e = new Entry<>(key, value, parent);
        //< 0 做爲節點的左子樹
       if (cmp < 0)
            parent.left = e;
        // > 0 做爲節點的右子樹
        else
            parent.right = e;
        //調整插入元素的樹結構,轉爲紅黑樹
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }

六)、TreeMap的get(K key)方法

步驟:

1).獲取根節點

2).從根節點開始比較左右子樹的key值

3).若樹中某一節點的key值與查找的key值相等,則返回對應的Entry<k, v>對象

treeMap.get("a");

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

final 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")
        //沒有比較器使用comparale的compareTo()規則
            Comparable<? super K> k = (Comparable<? super K>) key;
        Entry<K,V> p = root;
        //從根節點遍歷左右子樹,若key值相等,則返回當前節點對象
        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;
    }

注:TreeMap的功能比HashMap的功能強大, 實現了sortedMap接口,能夠對元素 進行排序,單TreeMap的性能卻略低於HashMap,當須要對集合進行排序操做可以使用TreeMap.

相關文章
相關標籤/搜索