TreeMap原理剖析

简介:

TreeMap是基于红黑树(一种自平衡的二叉查找树)实现的一个有序性的Map。注意该类并不是线程安全的,可以使用Collections.synchronizedSortedMap方法包装TreeMap使之转化成线程安全的map。要了解TreeMap必须先了红黑树原理。

TreeMap类图结构:
在这里插入图片描述

红黑树的介绍

红黑树(Red-Black Tree,简称R-B Tree),是一种特殊的平衡二叉树。其特点如下:
(1) 每个节点或者是黑色,或者是红色。
(2) 根节点是黑色,每个叶子节点(NIL节点,空节点)是黑色。
(3) 如果一个节点是红色的,则它的子节点必须是黑色的。
(4) 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

其示例如下:
在这里插入图片描述
在TreeMap添加删除元素的过程中保持红黑树的特性,则必须通过以下三种功能来保证:着色,左旋,右旋。

TreeMap主要方法如下:

1 put(K key, V value)方法:

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);
            //TreeMap的节点数+1
            size = 1;
             //TreeMap修改次数+1
            modCount++;
            return null;
        }
        // 使用cmp来表示排序比较结果
        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);
                // cmp < 0,表示新增节点的key小于当前节点的key,则以当前节点的左子节点作为新的当前节点
                if (cmp < 0)
                    t = t.left;
                 // cmp < 0,表示新增节点的key大于当前节点的key,则以当前节点的右子节点作为新的当前节点
                else if (cmp > 0)
                    t = t.right;
                else
                    // 比较结果等于0,说明key相等,覆盖旧值
                    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);
        }
        // 创建新节点e
        Entry<K,V> e = new Entry<>(key, value, parent);
        if (cmp < 0)
           // 将e放到当前节点的左边,作为左子树
            parent.left = e;
        else
         // 将e放到当前节点的右边,作为右子树
            parent.right = e;
        // 插入完成,对二叉树进行平衡操作:通过左旋(rotateLeft())、右旋(rotateRight())和着色(setColor)生成一个新的红黑树。
        fixAfterInsertion(e);
         //TreeMap的节点数+1
        size++;
         //TreeMap的修改次数+1
        modCount++;
        return null;
    }

2 get(Object key)方法:

public V get(Object key) {
    Entry<K,V> p = getEntry(key);
    return (p==null ? null : p.value);
}
final Entry<K,V> getEntry(Object key) {
    // 使用Comparator进行比较
    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;
    // 从根节点开始,不断比较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;
    }
    // 没有相等的key,返回null
    return null; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值