• 2.看TreeMap源码的deleteEntry方法遇到的问题


    问题场景

            在看TreeMap类是如何删除红黑树时,从remove方法看起,当看到deleteEntry(Entry<K,V> p)方法时:

    就是图中标红的三行代码:

            p.key = s.key;
            p.value = s.value;
            p = s;

            将后继节点的键赋值给待删除节点的键、将后继节点的值赋值给待删除节点的值、将p指向后继节点。

    我的疑惑

            已经将键和值都赋值给待删除的替换节点p了,为什么将p指向s?在这里我我错误的以为p节点指向s节点后,待删除节点的位置就变成s了。其实我这种理解完全错误。

    解决方案

            我产生这样的疑惑,是因为我没有完全理解变量、对象、方法区域;栈、堆之间的关系。在我经过几个小时的小纠结后,我得出的结论如下,用一张图直观的表示出来:

            p是变量,存储在栈中,而通过new创建出来的对象存储在堆中;栈中的变量通过指针指向堆中的对象。p.key = s.key语句将栈中变量指向的对象的key值变成栈中s变量所指向的对象的key值;p.value = s.value语句将栈中p变量所指向的对象的value值变成栈中s变量所指向的对象的value值;之后将栈中p变量指向s所指向的对象。这个解释算是很标准了。

           如果将这个问题放在红黑树中,p为树中一个待删除节点,s为p的后继节点。使用s的key、value值替换p的key和value值,在将p指向s,如果以p为中心的理解,很难理解,是个错误的方向。正确的理解方式:使用栈中s变量所指向的对象的key值和value值赋值给栈中p变量所指向的key值和value值,p所指向的对象是树中要删除被替换掉的节点,使用后继节点替换掉,赋值操作是指上就是在替换节点,而其父节点、左右子树都不用在重新赋值;之后再将栈中p变量指向堆中s之前所指向的对象。p之前所指向的对象在内存的堆中依旧存在,只是不能通过p直接访问了而已。

           在这里要总结一点:java中的变量只是堆中对象的引用,而不是真实的对象本身。变量只是一个对象的引用、变量只是一个对象的引用、变量只是一个对象的引用(重要的事说三遍)。

  • 相关阅读:
    Xcode Debugging
    GCD 深入理解
    iOS GCD编程
    iOS 面试之Block
    iOS SDWebImage 实现原理
    Block 初试
    通讯录
    UIScrollerView 的简单使用
    NSSet NSMutableSet的简单使用
    code
  • 原文地址:https://www.cnblogs.com/IdealSpring/p/11871185.html
Copyright © 2020-2023  润新知