一起来看源代码-01TreeMap添加操作

本文介绍了如何查看和理解Java的TreeMap源代码,特别是添加操作及其底层的红黑树原理。讲解了树结构、二叉树、排序二叉树和红黑树的概念,强调红黑树在查询效率上的优势。接着,详细阐述了TreeMap的结构,包括继承关系、实现的接口以及基本成员组成。最后,通过分析添加操作、左自旋和右自旋过程,以及案例演示,帮助读者深入理解TreeMap的内部工作方式和红黑树的自平衡策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文作者:黄海燕,叩丁狼高级讲师。原创文章,转载请注明出处。

##前言

之前很多小伙伴问我怎么看源代码,还有就是越来越多的程序员都想要看源代码,搞懂底层原理,但是感觉源代码非常的晦涩难懂,不够直接和清晰,所以我希望这篇文章能够快速带同学们看懂java源码,更加深入的学习java,帮助小伙伴们节约学习的时间成本.

##1.树的介绍

  • 什么是树结构?其实就是一个节点下面有多个子节点,我们称之为树结构,如下图:
  • 普通节点:拥有子节点的节点。
  • 叶子节点:没有子节点的节点。

树结构

什么是二叉树?

  • 二叉树就是一个节点最多只能有2个子节点,分为左节点和右节点,如下图:
    二叉树结构

什么是排序二叉树?

  • 若左子树不为空,则左子树所有节点的值小于根节点的值。
  • 若右子树不为空,则右子树所有节点的值大于根节点的值。
    如图:
    排序二叉树.png

什么是红黑树?
红黑树其实是一个平衡排序二叉树,属于查询高效的树结构.请看下图:
普通排序二叉树vs红黑树

查询元素6普通的二叉树需要操作6次,红黑树只需要操作4次,所以红黑树查询更加高效.

##1.TreeMap的结构介绍
###1.1 结构关系

public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable{

继承关系:

  • 父类AbstractMap,让子类拥有基本Map的方法,比如增(put)删(remove)查(get)等方法.

实现关系:

  • NavigableMap:父接口为SortedMap,所以NavigableMap为可排序接口,表示TreeMap但是一个排序的Map:
  • Cloneable:标记型的接口,内部都没有方法和属性,实现 Cloneable来表示该对象能被克隆,能使用Object.clone()方法。如果没有实现 Cloneable的类对象调用clone()就会抛出CloneNotSupportedException。
  • Serializable:标记型的接口,内部都没有方法和属性,实现Serializable表示可进行序列化和反序列化,表示能够使用在ObjectOutputStream.writeObject())和ObjectInputStream.readObject()

###1.2 基本成员组成

   /**
     * 比较器:类似于一个"裁判",用于比较插入对象和树节点的内容大小
     * 因为TreeMap是一个红黑树,红黑树是一个排序二叉树,插入元素的时候需要进行排序,排序可以使用比较器中的方式排序
     */
    private final Comparator<? super K> comparator;
    /**
     *  根节点
     */
    private transient Entry<K,V> root;
    /**
     * 树的元素个数
     */
    private transient int size = 0;
    /**
     * 操作次数:增加和删除操作数都会加1,用于控制并发修改异常
     */
    private transient int modCount = 0;

通过root根节点可以看出一个节点(元素)就是一个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;//颜色

节点表示如下:
树节点

###1.3添加操作:

public V put(K key, V value) {
        Entry<K, V> t = root;//和插入节点进行比较的树节点
        //根节点为空
        if (t == null) {
            compare(key, key); //key比key,自己比较自己,目的是想要检查类型,确保传入了比较器或者是key实现了可比较接口
            //创建了一个没有父节点的新的节点,作为根节点
            root = new Entry<>(key, value, null);
            size = 1;//元素个数为1
            modCount++;//操作数+1
            return null;//返回空,根节点添加结束
        }
        int cmp;//表示比较结果
        Entry<K, V> parent;
        // cpr临时表示比较器
        Comparator<? super K> cpr = comparator;
        if (cpr != null) {//比较器不为空,就使用比较器比较元素
            do {
                parent = t;//父节点为t
                cmp = cpr.compare(key, t.key);//通过比较器对key和树节点比较得到比较结果
                if (cmp < 0)//比较结果小于0,表示插入的元素比树节点小
                    t = t.left;//t往左走
                else if (cmp > 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值