TreeMap源码分析

TreeMap是基于红黑树来实现的,它是根据键的自然顺序,或者创建时提供的comparator来排序的。

1.属性

     /**
     * The comparator used to maintain order in this tree map, or
     * null if it uses the natural ordering of its keys.
     * TreeMap中的映射排序是根据此comparator来排序的,如果此comparator为null,则根据键的自然顺序排序
     * @serial
     */
    private final Comparator<? super K> comparator;
    // 根元素
    private transient Entry<K,V> root = null;

    /**
     * The number of entries in the tree
* 元素的数量
*/ private transient int size = 0; /** * The number of structural modifications to the tree.
* TreeMap修改的次数
*/ private transient int modCount = 0;

2.构造器

  /**
     * Constructs a new, empty tree map, using the natural ordering of its
     * keys.  All keys inserted into the map must implement the {@link
     * Comparable} interface.  Furthermore, all such keys must be
     * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw
     * a {@code ClassCastException} for any keys {@code k1} and
     * {@code k2} in the map.  If the user attempts to put a key into the
     * map that violates this constraint (for example, the user attempts to
     * put a string key into a map whose keys are integers), the
     * {@code put(Object key, Object value)} call will throw a
     * {@code ClassCastException}.
     */
    public TreeMap() {
        comparator = null;
    }

    /**
     * Constructs a new, empty tree map, ordered according to the given
     * comparator.  All keys inserted into the map must be <em>mutually
     * comparable</em> by the given comparator: {@code comparator.compare(k1,
     * k2)} must not throw a {@code ClassCastException} for any keys
     * {@code k1} and {@code k2} in the map.  If the user attempts to put
     * a key into the map that violates this constraint, the {@code put(Object
     * key, Object value)} call will throw a
     * {@code ClassCastException}.
     *
     * @param comparator the comparator that will be used to order this map.
     *        If {@code null}, the {@linkplain Comparable natural
     *        ordering} of the keys will be used.
* 构造一个空的TreeMap,根据指定的comparator来排序
*/ public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; } /** * Constructs a new tree map containing the same mappings as the given * map, ordered according to the <em>natural ordering</em> of its keys. * All keys inserted into the new map must implement the {@link * Comparable} interface. Furthermore, all such keys must be * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw * a {@code ClassCastException} for any keys {@code k1} and * {@code k2} in the map. This method runs in n*log(n) time. * * @param m the map whose mappings are to be placed in this map * @throws ClassCastException if the keys in m are not {@link Comparable}, * or are not mutually comparable * @throws NullPointerException if the specified map is null
* 构造一个TreeMap,包含给定的Map,按照key的自然顺序排序,key要实现Comparable接口
*/ public TreeMap(Map<? extends K, ? extends V> m) { comparator = null; putAll(m); } /** * Constructs a new tree map containing the same mappings and * using the same ordering as the specified sorted map. This * method runs in linear time. * * @param m the sorted map whose mappings are to be placed in this map, * and whose comparator is to be used to sort this map * @throws NullPointerException if the specified map is null
* 构造一个TreeMap,包含指定的Map,按照给定的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.方法

3.1:V put(K key,V value):将指定值与此映射中的指定键进行关联。如果该映射以前包含此键的映射关系,那么将替换旧值

插入操作可以分为两步:一是将该TreeMap看做一个二叉树来操作,找到将要插入的位置,然后进行插入操作。二是当插入操作完成后,为了保证红黑树的特性,需要对红黑树调整:节点旋转和颜色改变

 public V put(K key, V value) {
        Entry<K,V> t = root;
// 如果根节点为null,那么这个插入的数据将是根节点
if (t == null) { compare(key, key); // type (and possibly null) check root = new Entry<>(key, value, null); size = 1; modCount++; return null; }
// key值比较大小返回的比较结果
int cmp; Entry<K,V> parent; // split comparator and comparable paths Comparator<? super K> cpr = comparator;
// Comparator不为空的情况下,使用comparator来比较key值的大小,同时获取新插入节点的父节点parent
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); }
// Comparator为null的情况下,使用key的自然顺序进行排序,同时获取新插入节点的父节点parent
else { if (key == null) throw new NullPointerException(); 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; }

进入fixAfterInsertion方法:进行节点旋转和颜色改变。可以参照我的另一篇文章:红黑树详解 

 private void fixAfterInsertion(Entry<K,V> x) {
        x.color = RED;

        while (x != null && x != root && x.parent.color == RED) {
            if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
                Entry<K,V> y = rightOf(parentOf(parentOf(x)));
                if (colorOf(y) == RED) {
                    setColor(parentOf(x), BLACK);
                    setColor(y, BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    x = parentOf(parentOf(x));
                } else {
                    if (x == rightOf(parentOf(x))) {
                        x = parentOf(x);
                        rotateLeft(x);
                    }
                    setColor(parentOf(x), BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    rotateRight(parentOf(parentOf(x)));
                }
            } else {
                Entry<K,V> y = leftOf(parentOf(parentOf(x)));
                if (colorOf(y) == RED) {
                    setColor(parentOf(x), BLACK);
                    setColor(y, BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    x = parentOf(parentOf(x));
                } else {
                    if (x == leftOf(parentOf(x))) {
                        x = parentOf(x);
                        rotateRight(x);
                    }
                    setColor(parentOf(x), BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    rotateLeft(parentOf(parentOf(x)));
                }
            }
        }
        root.color = BLACK;
    }

3.2:V get(Object key):返回指定键所映射的值,如果对于该键而言,此映射不包含任何映射关系,则返回 null

  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)
// 如果Comparator不为null,则比较器使用Comparator,来获取对应的Value
return getEntryUsingComparator(key); if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; Entry<K,V> p = root;
// 否则使用key的自然排序来获取Value
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; }

3.3 remove (Object key):如果此 TreeMap 中存在该键的映射关系,则将其删除。

 

posted @ 2018-07-27 14:06  51life  阅读(179)  评论(0编辑  收藏  举报