源码分析三、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) {
        // 类型核查,比较器不为空,使用比较器,否则key实现Comparable接口
        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; // parent 指向最后一个节点
            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:

  1. NavigableMap接口的具体实现方法,并没有具体的写。
  2. TreeMap实际上就是一个树结构,从根节点触发,查找。通过put方法源码,发现除了Root根节点新增时是color=BLACK以外,每个新节点新增时都是RED,下一个节点新增时,fixAfterInsertion函数平衡二叉树后,父节点修改位BLACK。平衡二叉树,使用旋转方法,非平衡状态分为四种:左左、左右、右右、右左,具体的旋转方法理论,这里就不再描述了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值