TreeMap基于红黑树实现,在之前HashMap篇章中有所涉及,所以本篇重点不在此。上路~
containsKey() –> getEntry() –> getEntryUsingComparator()
|
|
虽然明面上是获取值的方法,本质却是比出个高低等。这里将Java的java.util.Comparator(比较器排序)、java.lang.Comparable(自然排序)都用到了。顺便补了两者知识点(见文末①)。当然这里好奇的是源码中将使用comparator比较独立提成方法,说是能提高性能。why?反向思考下,假使将getEntryUsingComparator()方法内代码放回getEntry()似乎也就多了一对“{}”。费解- -
顺带一提,如果你还记得之前文章中的HashMap也用到了红黑树,而它先比较的hash再比key值,这比较的是key值。
put() –> compare() –> fixAfterInsertion()
|
|
“compare(key, key);”是一个有意思写法。从注释直译就是类型(为null可能性)检查。为空检查很好理解,因为null.xx()肯定跑异常,至于类型检查笔者理解是要求键值实现Comparable接口。
“from CLR”是指Cormen, Leiserson, Rivest,他们是算法导论的作者,也就是说TreeMap里面算法都是参照算法导论的伪代码。
由于TreeMap的有序性,使其增删查都是先进行比较,找到合适的位置。fixAfterInsertion()在这的作用类似HashMap中的balanceInsertion(),修复红黑树性质。
deleteEntry() –> successor() –> fixAfterDeletion()
|
|
successor()可以简单的理解为“一个升序数组a[index],successor即为a[index+1]”。相对的还有prodecessor()。源码中可能出现的情况抽象如下图(while只举一次循环为例)。
deleteEntry调用successor时,由于right != null,所以不会出现③ ④ ⑤的情况。基本思路就是找到“a[index+1]”(p)替换待删节点,然后使“a[index+1]”的子节点(replacement)指向其父节点(Link replacement to parent),最后清p、fixAfterDeletion修复红黑树性。
如果觉得这个看懂了,可以挑战下HashMap.TreeNode.removeTreeNode()。
说点什么:
TreeMap 有序;非线程安全;key值不支持null…;
实现了NavigableMap接口(见文末②),NavigableMap具有了针对给定搜索目标返回最接近匹配项的导航方法。
如: lowerEntry、floorEntry、ceilingEntry 和 higherEntry 分别返回与小于、小于等于、大于等于、大于给定键的 Map.Entry对象,如果不存在这样的键,则返回 null。
实现了SortedMap接口:它用来保持键的有序顺序,也提供了范围检索的一些方法;
如: headMap、subMap、tailMap分别返回小于结束键、大于或等于开始和小于结束键、大于或等于开始键的Map.Entry对象。
添加到SortedMap实现类的元素必须实现Comparable接口,否则您必须给它的构造函数提供一个Comparator接口的实现。TreeMap类是它的唯一一份实现。
知识点:
①Java中自然排序和比较器排序详解:Comparable与Comparator;
②计算机程序的思维逻辑 (43) - 剖析TreeMap:方法应用举例;