Java-第十五部分-源码解读-TreeMap

114 阅读3分钟

源码解读全文

TreeHashMap

  • 节点构成一个红黑树/二叉搜索平衡树

Entry

  • 树结构的节点
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;

    /**
     * Make a new cell with given key, value, and parent, and with
     * {@code null} child links, and BLACK color.
     */
    Entry(K key, V value, Entry<K,V> parent) {
        this.key = key;
        this.value = value;
        this.parent = parent;
    }

put

public V put(K key, V value) {
    Entry<K,V> t = root;
    if (t == null) { //根节点为null
        compare(key, key); //用key的compare进行比较自己,相当于没比较
        root = new Entry<>(key, value, null); //当前key作为root
        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 { //没有自定义比较器,用key的比较方式
        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;
}
  • compare,用key的比较方式进行比较,或者用传入的比较方式
final int compare(Object k1, Object k2) {
    return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
        : comparator.compare((K)k1, (K)k2);
}

get

public V get(Object key) {
    Entry<K,V> p = getEntry(key);
    return (p==null ? null : p.value);
}
  • getEntry,搜索树的搜索方式
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")
        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;
}

remove

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

    V oldValue = p.value;
    deleteEntry(p);
    return oldValue;
}
  • deleteEntry
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) {
        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.
        //帮助gc
        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; //帮助gc
        }
    }
}
  • successor,二叉树的继任策略
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;
    }
}

higherKey

  • getLowerEntry过程镜像对称
  • 大于 key 的节点
public K higherKey(K key) {
    //null处理
    return keyOrNull(getHigherEntry(key));
}
  • getHigherEntry二分查找
final Entry<K,V> getHigherEntry(K key) {
    Entry<K,V> p = root;
    while (p != null) {
        int cmp = compare(key, p.key);
        if (cmp < 0) { key < p.key
            if (p.left != null) //左边还有,就在左边找
                p = p.left;
            else //没有直接返回
                return p;
        } else { // >=
            if (p.right != null) { //当前节点有右子节点,那么往下找
                p = p.right;
            } else { //没有,则找中序遍历的继任节点,且此时找到的节点一定比key大
                //原因是,由上往下找,已经找到了parent.right 不存在
                //key一定比parent.parent.key 小
                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;
}

ceilingKey

  • getFloorEntry对称
  • 返回一个大于等于 key 的节点
public K ceilingKey(K key) {
    return keyOrNull(getCeilingEntry(key));
}
  • getCeilingEntry
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;
}

lastKey

public K lastKey() {
    return key(getLastEntry());
}
  • getLastEntry最右边的节点
final Entry<K,V> getLastEntry() {
    Entry<K,V> p = root;
    if (p != null)
        while (p.right != null)
            p = p.right;
    return p;
}

firstKey

public K firstKey() {
    return key(getFirstEntry());
}
  • getFirstEntry最左边的节点
final Entry<K,V> getFirstEntry() {
    Entry<K,V> p = root;
    if (p != null)
        while (p.left != null)
            p = p.left;
    return p;
}

小结

  • 维护二叉搜索平衡树/红黑树的结构
  • 大小顺序逻辑上的是通过中序遍历实现的