1. 程式人生 > >原始碼分析三、Map(3)-TreeMap

原始碼分析三、Map(3)-TreeMap

一、概述

通過IDEA看下TreeMap的繼承關係,繼承抽象父類AbstractMap,實現了NavigableMap介面,SortedMap介面,TreeMap是一種有序的Map,從其實現的介面就能看出來。

那麼,首先來看下實現的兩類介面:

  1. SortedMap:實現該介面的類,必須按照一定的排序規則保證key的有序性,可以根據key的compareTo()函式或者在構造器中傳入Comparator介面的實現類來排序,集合檢視遍歷的順序也應與key的順序一致。
  2. NavigableMap:實現該介面的類,需實現一些導航方法

TreeMap類,基於紅黑樹,一種自平衡的二叉查詢樹,插入和查詢的時間複雜度只用O(log n)。

二叉查詢樹:

  • 任意節點最多含有兩個子節點。
  • 任意節點的左、右節點都可以看做為一棵二叉查詢樹。
  • 如果任意節點的左子樹不為空,那麼左子樹上的所有節點的值均小於它的根節點的值。
  • 如果任意節點的右子樹不為空,那麼右子樹上的所有節點的值均大於它的根節點的值。
  • 任意節點的key都是不同的。

但是,二叉查詢樹,在有序的集合下,就會呈現出只有一個分支的情況,例如遞增序列,那麼二叉樹就只有右分支,為了使得這種情況不發生,引入了自平衡,即在樹結構傾斜時,通過旋轉操作讓樹趨於平衡。

紅黑樹,就是一種自平衡的二叉查詢樹,根據字面理解,節點只有兩種狀態,非黑即紅,兩種著色。TreeMap中的每個Entry節點,就是基於這種節點結構

,見原始碼。

二、原始碼分析

1.SortedMap介面:

public interface SortedMap<K,V> extends Map<K,V> {
    /**
     * 返回比較器去對map的key進行排序,否則使用key的自然排序(key自身的compareTo函式)
     */
    Comparator<? super K> comparator();

    /**
     * 返回一個key從fromKey到toKey的左閉右開的子Map(對子Map的修改,會影響原Map集合)
     */
    SortedMap<K,V> subMap(K fromKey, K toKey);

    // 返回嚴格小於toKey的子map(對子Map的修改,會影響原Map集合)
    SortedMap<K,V> headMap(K toKey);

    // 返回嚴格大於fromKey的子map(對子Map的修改,會影響原Map集合)
    SortedMap<K,V> tailMap(K fromKey);

    // 返回當前集合第一個key
    K firstKey();

    // 返回當前map最後一個key
    K lastKey();

    // 三類集合檢視
    Set<K> keySet();

    Collection<V> values();

    Set<Map.Entry<K, V>> entrySet();
}

2.NavigableMap介面:

public interface NavigableMap<K,V> extends SortedMap<K,V> {     // 返回比指定key小的,最大的key對應的鍵值對,如果找不到則返回null     Map.Entry<K,V> lowerEntry(K key);

    // 返回比指定key小的,最大的key,如果找不到則返回null     K lowerKey(K key);

    // 返回比指定key小於等於的,最大的key對應的鍵值對,如果找不到則返回null     Map.Entry<K,V> floorEntry(K key);

   // 返回比指定key小於等於的,最大的key,如果找不到則返回null     K floorKey(K key);

    // 返回比指定key大於等於的,最小的key對應的鍵值對,如果找不到則返回null     Map.Entry<K,V> ceilingEntry(K key);

    // 返回比指定key大於等於的,最小的key,如果找不到則返回null     K ceilingKey(K key);

    // 返回比指定key大於的,最小的key對應的鍵值對,如果找不到則返回null     Map.Entry<K,V> higherEntry(K key);

    // 返回比指定key大於的,最小的key,如果找不到則返回null     K higherKey(K key);

    // 返回第一個的鍵值對     Map.Entry<K,V> firstEntry();

    // 返回最後一個鍵值對     Map.Entry<K,V> lastEntry();

    // 移除並返回第一個鍵值對     Map.Entry<K,V> pollFirstEntry();

    // 移除並返回最後一個鍵值對     Map.Entry<K,V> pollLastEntry();

    // 返回當前順序相反的集合檢視     NavigableMap<K,V> descendingMap();

    // 返回當前map中所有key的集合檢視     NavigableSet<K> navigableKeySet();

   // 返回當前map中所有key的反序的集合檢視     NavigableSet<K> descendingKeySet();

    // 類似於SortedMap裡的subMap擷取子map,區別是這裡指定區間包含屬性,是開還是閉     NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,                              K toKey,   boolean toInclusive);

    // 擷取tokey之前的map,控制是否包含指定的toKey     NavigableMap<K,V> headMap(K toKey, boolean inclusive);

    // 擷取fromKey之後的map,控制是否包含指定的fromKey     NavigableMap<K,V> tailMap(K fromKey, boolean inclusive);

    // 與SortedMap擷取一致,左閉右開     SortedMap<K,V> subMap(K fromKey, K toKey);

    // 擷取子map,不包含指定toKey     SortedMap<K,V> headMap(K toKey);

    // 擷取子map,不包含指定fromKey     SortedMap<K,V> tailMap(K fromKey); }

3.TreeMap類:

Map類通用的方法不在原始碼裡重複。

3.1.建構函式

public class TreeMap<K,V>     extends AbstractMap<K,V>     implements NavigableMap<K,V>, Cloneable, java.io.Serializable {     // 比較器     private final Comparator<? super K> comparator;

   // Root節點(根節點)

    private transient Entry<K,V> root;

    // 節點個數     private transient int size = 0;

    // 樹內節點修改次數     private transient int modCount = 0;

    // 預設建構函式,預設使用Key的排序規則進行排序     public TreeMap() {         comparator = null;     }

    // 提供比較器的建構函式     public TreeMap(Comparator<? super K> comparator) {         this.comparator = comparator;     }

    // 提供指定Map集合的建構函式,即使用指定Map的key比較器,對指定Map進行排序     public TreeMap(Map<? extends K, ? extends V> m) {         comparator = null;         putAll(m);     }

    // 提供指定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) {         }     }

 3.2.內部類

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

/**
 * TreeMap節點
 */
static final class Entry<K,V> implements Map.Entry<K,V> {
    K key;
    V value;
    Entry<K,V> left;
    Entry<K,V> right;
    Entry<K,V> parent;
    boolean color = BLACK;

    /**
     * 建立新的節點,指定key、value、父節點以及color為黑
     */
    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;
    }
}

 3.3.內部方法(default包內可見)

// 根據指定的key,查詢對應的鍵值對
final Entry<K,V> getEntry(Object key) {
    // 如果比較器不為空,使用比較器
    if (comparator != null)
        return getEntryUsingComparator(key);
    if (key == null)
        throw new NullPointerException();
    @SuppressWarnings("unchecked")
        Comparable<? super K> k = (Comparable<? super K>) key;
    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;
}
/**
 * 用於getEntry的有比較器的獲取entry,用的很少
 從根節點出發,往左、往右節點查詢
 */
final Entry<K,V> getEntryUsingComparator(Object key) {
    @SuppressWarnings("unchecked")
        K k = (K) key;
    Comparator<? super K> cpr = comparator;
    if (cpr != null) {
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = cpr.compare(k, p.key);
            if (cmp < 0)
                p = p.left;
            else if (cmp > 0)
                p = p.right;
            else
                return p;
        }
    }
    return null;
}

// 找第一個節點,實際上,找到最左端的節點

final Entry<K,V> getFirstEntry() {
    Entry<K,V> p = root;
    if (p != null)
        while (p.left != null)
            p = p.left;
    return p;
}

// 找到最後一個節點,實際上,找到最右端的節點

final Entry<K,V> getLastEntry() {
    Entry<K,V> p = root;
    if (p != null)
        while (p.right != null)
            p = p.right;
    return p;
}

// 返回指定key最近的一個元素,先返回右邊的

static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {
    if (t == null)
        return null;
    else if (t.right != null) {
        Entry<K,V> p = t.right;
        while (p.left != null)
            p = p.left;
        return p;
    } else {
        Entry<K,V> p = t.parent;
        Entry<K,V> ch = t;
        while (p != null && ch == p.right) {
            ch = p;
            p = p.parent;
        }
        return p;
    }
}

// 返回指定Entry的key

static <K> K key(Entry<K,?> e) {
    if (e==null)
        throw new NoSuchElementException();
    return e.key;
}
/**
 * 刪除指定節點,並進行修改,以維持平衡
 */
private void deleteEntry(Entry<K,V> p) {
    modCount++;
    size--;

    // If strictly internal, copy successor's element to p and then make p
    // point to successor.
    if (p.left != null && p.right != null) {
        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.
    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);
    } 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;
        }
    }
}

3.4.查詢操作

// 是否包含指定的value,遍歷順序和key一致
public boolean containsValue(Object value) {
    for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))
        if (valEquals(value, e.value))
            return true;
    return false;
}
public K firstKey() { // 返回第一個key
    return key(getFirstEntry());
}
public K lastKey() { // 返回最後一個key
    return key(getLastEntry());
}

// NavigableMap的具體實現方法,具體功能見上介面說明

// TreeMap實現使用二叉樹的遍歷邏輯查詢

final Entry<K,V> getCeilingEntry(K key) {
    Entry<K,V> p = root;
    while (p != null) {
        int cmp = compare(key, p.key);
        if (cmp < 0) {
            if (p.left != null)
                p = p.left;
            else
                return p;
        } else if (cmp > 0) {
            if (p.right != null) {
                p = p.right;
            } else {
                Entry<K,V> parent = p.parent;
                Entry<K,V> ch = p;
                while (parent != null && ch == parent.right) {
                    ch = parent;
                    parent = parent.parent;
                }
                return parent;
            }
        } else
            return p;
    }
    return null;
}

// 小於指定key最大的key
final Entry<K,V> getFloorEntry(K key) {
    Entry<K,V> p = root;
    while (p != null) {
        int cmp = compare(key, p.key);
        if (cmp > 0) {
            if (p.right != null)
                p = p.right;
            else
                return p;
        } else if (cmp < 0) {
            if (p.left != null) {
                p = p.left;
            } else {
                Entry<K,V> parent = p.parent;
                Entry<K,V> ch = p;
                while (parent != null && ch == parent.left) {
                    ch = parent;
                    parent = parent.parent;
                }
                return parent;
            }
        } else
            return p;

    }
    return null;
}

// 大於指定key的最小key
final Entry<K,V> getHigherEntry(K key) {
    Entry<K,V> p = root;
    while (p != null) {
        int cmp = compare(key, p.key);
        if (cmp < 0) {
            if (p.left != null)
                p = p.left;
            else
                return p;
        } else {
            if (p.right != null) {
                p = p.right;
            } else {
                Entry<K,V> parent = p.parent;
                Entry<K,V> ch = p;
                while (parent != null && ch == parent.right) {
                    ch = parent;
                    parent = parent.parent;
                }
                return parent;
            }
        }
    }
    return null;
}

// 小於指定key的最大key
final Entry<K,V> getLowerEntry(K key) {
    Entry<K,V> p = root;
    while (p != null) {
        int cmp = compare(key, p.key);
        if (cmp > 0) {
            if (p.right != null)
                p = p.right;
            else
                return p;
        } else {
            if (p.left != null) {
                p = p.left;
            } else {
                Entry<K,V> parent = p.parent;
                Entry<K,V> ch = p;
                while (parent != null && ch == parent.left) {
                    ch = parent;
                    parent = parent.parent;
                }
                return parent;
            }
        }
    }
    return null;
}

3.5.新增操作

// 新增指定Map到TreeMap中,如果是SortedMap,使用特殊的方法,否則使用通用方法

public void putAll(Map<? extends K, ? extends V> map) { 
    int mapSize = map.size();
    if (size==0 && mapSize!=0 && map instanceof SortedMap) {
        Comparator<?> c = ((SortedMap<?,?>)map).comparator();
        if (c == comparator || (c != null && c.equals(comparator))) {
            ++modCount;
            try {
                buildFromSorted(mapSize, map.entrySet().iterator(),
                                null, null);
            } catch (java.io.IOException cannotHappen) {
            } catch (ClassNotFoundException cannotHappen) {
            }
            return;
        }
    }
    super.putAll(map);
}
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);
    }
    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);
    }
    Entry<K,V> e = new Entry<>(key, value, parent);
    if (cmp < 0)
        parent.left = e;
    else
        parent.right = e;
    fixAfterInsertion(e);
    size++;
    modCount++;
    return null;
}

3.6.刪除操作

public V remove(Object key) {
    Entry<K,V> p = getEntry(key);
    if (p == null)
        return null;

    V oldValue = p.value;
    deleteEntry(p);
    return oldValue;
}

PS:NavigableMap介面的具體實現方法,並沒有具體的寫。