- 前言
TreeMap是由 Red-Black Tree实现的。Red-Black Tree具备几个重要的性质: 1.根是Black的;2.叶子是Black的;3.不能存在两个连续的Red节点;4.任何一个节点到它的叶子节点的路径上黑色节点个数要相同。如果不满足性质3或者4的时候,就会对树进行旋转操作。Red-Black Tree的统计性能要好于AVL,所以TreeMap使用的是Red-Black Tree实现平衡二叉树。
由于使用的是平衡二叉树,因此containsKey,get,put,remove等操作都是log(n)的。源代码中的平衡二叉树参考的《Introduction to Algorithm》。
TreeMap是线程不安全的,Collections里面有很多静态方法能生成很多synchronized的容器,这些容器与原容器的区别在于,它们多了一个显式的域mutex,用于加锁(synchronized)。不推荐使用,java.util.concurrent包中有许多线程安全的容器。
- 代码分析
内部类:Entry与HashMap.Entry相比明显不同,HashMap.Entry是链表结构,TreeMap.Entry是二叉树结构。
方法:getEntry(Object key)经典的二叉树查询操作,如果使用默认的Comparator,必须为key的类型实现Comparable接口。否则就会有java.lang.ClassCastException。
方法:getCeilingEntry(K key)——ceiling是天花板的意思。
如果key不存在,返回距离key最近的且大于key的Entry。
方法:getFloorEntry(K key)与该方法刚刚相反——Floor是地板的意思。
扯远一点,Math中有floor,ceil与round三种方法,floor就是取小于x的最大整数,ceil与floor相反,大于x的最小整数,round是x+0.5向下取整。
方法:put(K key, V value)
截取了最后部分的代码,可以看到在插入之后会调用fixAfterInsertion()方法调整红黑树。
- TreeMap与HashMap相比
- 相同点
- 键值对保存数据
- 不是synchronized
- 不同点
- TreeMap需要用户提供Comparator,或者Key实现Comparable接口
- TreeMap的操作虽然是logN,但是是有前提的,那就是compare的过程要是O(1)
- TreeMap的扩容代价小于HashMap
- 相同点