1. Treeset
我们都知道,是一个有序的集合。
但是如果分析TreeSet的实现源码,会发现构造方法中存在 TreeMap。
换句话说: TreeSet的底层就是通过TreeMap来实现
2. TreeMap
TreeMap 的实现就是红黑树数据结构,也就说是一棵自平衡的排序二叉树,这样就可以保证当需要快速检索指定节点。
向TreeMap中每次Put一对Entry时,实际上是给红黑树中添加一个节点。这种方式保证Key总是从小到大有序排列。
对于 TreeMap 而言,由于它底层采用一棵“红黑树”来保存集合中的 Entry,这意味这 TreeMap 添加元素、取出元素的性能都比 HashMap 低:
当 TreeMap 添加元素时,需要通过循环找到新增 Entry 的插入位置,因此比较耗性能;当从 TreeMap 中取出元素时,需要通过循环才能找
到合适的 Entry,也比较耗性能。但 TreeMap、TreeSet 比 HashMap、HashSet 的优势在于:TreeMap 中的所有 Entry 总是按 key 根据指
定排序规则保持有序状态,TreeSet 中所有元素总是根据指定排序规则保持有序状态。
3. java实现的红黑树
有如下几个性质:
- 性质 1:每个节点要么是红色,要么是黑色。
- 性质 2:根节点永远是黑色的。
- 性质 3:所有的叶节点都是空节点(即 null),并且是黑色的。
- 性质 4:每个红色节点的两个子节点都是黑色。(从每个叶子到根的路径上不会有两个连续的红色节点)
- 性质 5:从任一节点到其子树中每个叶子节点的路径都包含相同数量的黑色节点。
红黑树并不是真正的平衡二叉树,但在实际应用中,红黑树的统计性能要高于平衡二叉树,但极端性能略差。
由此我们可以得出结论:对于给定的黑色高度为 N 的红黑树,从根到叶子节点的最短路径长度为 N-1,最长路径长度为 2 * (N-1)
红黑树操作
每次插入数据,红黑树都会有简单的修复和选择,以保证树的性质。
在红黑树上进行插入操作和删除操作会导致树不再符合红黑树的特征,因此插入操作和删除操作都需要进行一定的维护,以保证插入节点、删除节点后的树依然是红黑树。
实现
TreeMap 插入节点的修复由方法实现fixAfterInsertion(Entry<K,V> x)
删除节点的修复由方法 fixAfterDeletion(Entry<K,V> x) 实现
对结构整体循环重新赋予颜色
get方法由getEntry方法实现。
getEntry(Object obj) 方法也是充分利用排序二叉树的特征来搜索目标 Entry,程序依然从二叉树的根节点开始,如果被搜索节点大于当前节点,程序向“右子树”搜索;如果被搜索节点小于当前节点,程序向“左子树”搜索;如果相等,那就是找到了指定节点。
从内部结构来看,TreeMap 本质上就是一棵“红黑树”,而 TreeMap 的每个 Entry 就是该红黑树的一个节点。