TreeMap底层原理

一、什么是TreeMap

TreeMap特点:添加的键是可排序、不重复、无索引的

TreeMap主要红黑树的数据结构实现

二、TreeMap源码

put方法

    public V put(K key, V value) {
        return put(key, value, true);
    }

 此处我们能够看到调用put方法后又调用了三个参数的put方法,而第三个参数作用就是是否替换掉重复键的值。

    private V put(K key, V value, boolean replaceOld) {
        //创建一个节点变量为root
        Entry<K,V> t = root;
        //如果节点变量是空,则调用addEntryToEmptyMap方法
        if (t == null) {
            addEntryToEmptyMap(key, value);
            return null;
        }
        //下面的操作只有在根节点有值时才会运行
        //初始化一个比较变量,用于比较键的大小
        int cmp;
        //初始化一个父亲节点
        Entry<K,V> parent;
        // split comparator and comparable paths
        //赋值比较器,如果构造函数为空参则比较器为null
        Comparator<? super K> cpr = comparator;
        //如果在初始化时传参了比较器则if为true
        if (cpr != null) {
            do {
                //parent记录下添加节点应该放在哪个父亲节点下
                parent = t;
                //此处使用传入的比较器,得出添加的节点和父系节点的key的结果值
                cmp = cpr.compare(key, t.key);
                //如果结果值小于0则t=t的左节点如果大于0则放在右节点。
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                //如果等于0则说明key相同,要将值(value)覆盖掉
                else {
                    V oldValue = t.value;
                    if (replaceOld || oldValue == null) {
                        t.value = value;
                    }
                    return oldValue;
                }
            } while (t != null);
        } else {
            //此处处理使用的比较器不同其他操作与上面类似
            Objects.requireNonNull(key);
            @SuppressWarnings("unchecked")
            Comparable<? super K> k = (Comparable<? super K>) key;
            do {
                parent = t;
                //这里使用key类型实现的比较器
                cmp = k.compareTo(t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else {
                    V oldValue = t.value;
                    if (replaceOld || oldValue == null) {
                        t.value = value;
                    }
                    return oldValue;
                }
            } while (t != null);
        }
        //添加节点,通过parent和cmp确定需要添加的位置
        addEntry(key, value, parent, cmp < 0);
        return null;
    }

1、首次添加

三个参数的put方法上来先是创建了一个变量赋值根节点,判断根节点是否为空如果为空调用addEntryToEmptyMap方法。

    private void addEntryToEmptyMap(K key, V value) {
        compare(key, key); // type (and possibly null) check
        root = new Entry<>(key, value, null);
        size = 1;
        modCount++;
    }

这里先是调用了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);
    }

此方法对key进行了类型强转,如果key没有继承Comparable则会报错,所以这里这个方法真实作用是检查key是否继承了Comparable。

例如:

    public static void main(String[] args) {
        Map<Object, Object> map = new TreeMap<>();
        Student student = new Student();
        map.put(student, 1);
    }

我这里Student类并没有继承Comparable。

运行后则会报出

其报错位置就在compare方法内。

2、后续添加

中间获取parent和cmp的步骤请看注解

最后根据parent和cmp调用addEntry方法添加节点。

    private void addEntry(K key, V value, Entry<K, V> parent, boolean addToLeft) {
        Entry<K,V> e = new Entry<>(key, value, parent);
        if (addToLeft)
            parent.left = e;
        else
            parent.right = e;
        fixAfterInsertion(e);
        size++;
        modCount++;
    }

该方法先创建了一个节点对象。确定父亲节点。再根据addToLeft确定放在父亲节点左边还是右边。最后调用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;
    }

  • 21
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TreeMap是基于红黑树的NavigableMap实现。红黑树是一种自平衡二叉查找树,它具有以下特点:节点可以是红色或黑色,根节点和叶子节点(NIL节点)都是黑色的;如果一个节点是红色的,则它的子节点必须是黑色的;从根节点到叶子节点的所有路径上,黑色节点的数量是相同的;任意节点到其每个叶子节点的所有简单路径都包含相同数量的黑色节点。 TreeMap的最重要特点是它可以对添加进来的元素进行排序。根据键的自然顺序进行排序,或者根据创建映射时提供的Comparator进行排序,具体取决于使用的构造方法。如果没有提供Comparator,则按照键的自然顺序进行排序。 TreeMap底层实现使用红黑树来存储元素。通过红黑树的特性,TreeMap可以高效地进行插入、删除和查找操作。红黑树的平衡性能保证了这些操作的时间复杂度为O(logN)。 总结来说,TreeMap是一个可排序的集合,它使用红黑树作为底层数据结构来存储元素,并根据键的自然顺序或自定义Comparator来进行排序。这使得TreeMap能够在插入、删除和查找操作上具有较好的性能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [TreeMap 底层原理](https://blog.csdn.net/qq_33419463/article/details/90811993)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值