TreeMap概述
首先TreeMap是实现了NavigableMap和SortMap的Map,从实现的角度说是红黑树。
红黑树
红黑树是平衡搜索树的一种,也是使用最多的一种树,其特点
- 对于所有的动态集合操作都可以保证以最坏O(lgn)的时间复杂度来运行。
- 每个节点都包含一个储存位来表示节点的颜色,非红即黑。
- 通过对任何一条从根节点到叶子节点的简单路径上各个节点的颜色进行约束,红黑树确保没有一条路径会比其他路径长出2倍,而是近似平衡的。
红黑性质:
- 每个节点或是红色或是黑色
- 根节点是黑色
- 每个叶节点是黑色
- 如果一个节点是红色,则它的两个子节点都是红色
- 对于每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
从某节点出发到达一个叶节点的任意一条简单路径上的黑色节点数称为黑高。红黑树的黑高就是其根的黑高。
- 一棵有n个内部节点的红黑树的高度至多为2lg(n+1)。
相对于其他平衡树,因为他的插入和删除操作只要最多3次左旋或者右旋就可以完成,因此相对于AVL树它的插入和删除效率更高,但由于其不是高度平衡树,其查询效率略低于AVL树。
当然红黑树插入和删除操作是比较复杂的。这里不详细描述等到代码里再说。
静态域和静态方法
静态域:
private static final boolean RED = false;
private static final boolean BLACK = true;
表示红黑节点颜色的bool值。这种用法类似于C++中的宏定义
private static final Object UNBOUNDED = new Object();
表示对于subMap不可访问的区域。
大部分就是获得或者设置节点的域没什么好说的,这里重点说几个有意思的。
- computeRedLevel用途不明;
后续会介绍到。 - exportEntry用于返回Entry,但是并不返回TreeMap的节点,而是返回AbstractMap.SimpleImmutableEntry类型。
static <K,V> Map.Entry<K,V> exportEntry(TreeMap.Entry<K,V> e) {
return (e == null) ? null :
new AbstractMap.SimpleImmutableEntry<>(e);
}
ExportEntry返回一个AbstractMap.SimpleImmutableEntry<>(e)。这很有意思。这个AbstractMap.SimpleImmutableEntry<>(e)是给静态内部类,所以可以单独初始化。
- 前驱和后继
当然前驱和后继的算法是相同的,这里只看一个。
static <K,V> Entry<K,V> predecessor(Entry<K,V> t) {
if (t == null)
return null;
else if (t.left != null) {
Entry<K,V> p = t.left;
while (p.right != null)
p = p.right;
return p;
} else {
Entry<K,V> p = t.parent;
Entry<K,V> ch = t;
while (p != null && ch == p.left) {
ch = p;
p = p.parent;
}
return p;
}
}
先判断t是否为空,如果为空则找t节点的做节点,如果左节点存在则很显然其左节点就是前驱节点,如果左节点为空,则需要向上溯源。直到当前节点是其父节点的右节点,则父节点就是前驱节点。当然这段程序是针对BST来说的。所以所有的BST都可以用类似的方法实现。
域
内部域很简单,主要就是root,size,和comparator。其他的内容是由于需要返回视图而设置的。意义也很明显
内部类
Treemap的内部类和之前说HashMap的内部类是类似的,大部分都是为了实现map需要返回视图的要求,或者迭代器的要求来实现的 。
Entry
K key;
V value;
Entry<K,V> left = null;
Entry<K,V> right = null;
Entry<K,V> parent;
boolean color = BLACK;
其他部分的内容并没有什么特别需要说明的,只看下equals和hashCode
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
}
static final boolean valEquals(Object o1, Object o2) {
return (o1==null ? o2==null : o1.equals(o2));
}
equals先做类型检查,然后仅仅考虑key和value是否相同,然后调用的静态valEquals屏蔽了null和object的区别。
key、value和Entry视图类
类似于HashMap,这几个类都是private的内部类,然后通过一个public方法返回set或者collections类型的视图。通常来说这几个内部类都不实现方