源码学习day03 (TreeMap)

源码学习day03 (TreeMap)

基本参数

	/**
     * 比较器,用于维护map中元素的顺序
     */
	 private final Comparator<? super K> comparator;
	/**
     * 定义根节点
     */
    private transient Entry<K,V> root;

    /**
     * 树中元素的大小
     */
    private transient int size = 0;

    /**
     * 修改次数
     */
    private transient int modCount = 0;

构造器

/**
 * 无参构造器
 */
  public TreeMap() {
        comparator = null;
    }
/**
 * 有参构造器,自定义排序方法
 */
  public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }
/**
 * 有参构造器,按照传入map集合的顺序将集合加入TreeMap
 */
 public TreeMap(Map<? extends K, ? extends V> m) {
        comparator = null;
        putAll(m);
    }
/**
 * 有参构造器,按照传入map集合的顺序将集合加入TreeMap,并指定比较器的值
 */
 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) {
        }
    }    

主要代码解析

   public V put(K key, V value) {
   		//用t表示二叉树当前节点
        Entry<K,V> t = root;
        if (t == null) {
        //判断key是否可以进行比较
            compare(key, key); // type (and possibly null) check
			//因为root节点为空,所以直接赋值
            root = new Entry<>(key, value, null);
            //size值+1
            size = 1;
            modCount++;
            return null;
        }
        //cmp表示key排序的返回结果
        int cmp;
        //父节点
        Entry<K,V> parent;
        // split comparator and comparable paths
        Comparator<? super K> cpr = comparator;
        //比较器不为null时执行
        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")
           //采用默认的排序算法进行创建TreeMap集合
                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);
        }
        //如果新增节点的key小于parent的key,则当做左子节点
        //如果新增节点的key大于parent的key,则当做右子节点
        Entry<K,V> e = new Entry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        /
	* 上面已经完成了排序二叉树的的构建,将新增节点插入该树中的合适位置
	* 下面fixAfterInsertion()方法就是对这棵树进行调整、平衡,
	* 具体过程参考上面的五种情况
	*/
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }
/**
* 移除节点的方法
*/
 public V remove(Object key) {
 //判断书中是否存在该值
     Entry<K,V> p = getEntry(key);
     if (p == null)
         return null;
	//如果存在
    V oldValue = p.value;
    deleteEntry(p);
    return oldValue;
    }
/**
* 删除的核心方法
*/
  private void deleteEntry(Entry<K,V> p) {
        modCount++;
        size--;
		//判断要删除节点是否有左右孩子节点
        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

       //找出要替换的节点
        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;

            p.left = p.right = p.parent = null;

            //检查要删除节点颜色,如果是黑色,则要重新将红黑树排序
            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;
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值