public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable
{
...
}
TreeMap 的接口几继承树中,有两个与众不同的接口:NavigableMap、SortedMap。SortedMap接口表示它的key是有序不能重复的,支持获取头尾Key-Value 元素,或者更具key指定范围获取子集合等。插入的key 必须实现Comparable 或者提供额外的Comparator,所以key不允许为null,但是value 可以。NavigablMap接口继承了Sorted Map接口。
如果key没有实现Comparable或者Comparator,那么编译的时候会抛出异常。
import java.util.TreeMap;
public class TreeMapDemo {
public static void main(String[] args) {
TreeMap<Person,Integer> tree = new TreeMap<>();
tree.put(new Person(1,"张三"), 1);
}
}
class Person{
private int age;
private String name;
getter/setter/constructor/toString
}
output:
Exception in thread "main" java.lang.ClassCastException: class Person cannot be cast to class java.lang.Comparable (Person is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')
at java.base/java.util.TreeMap.compare(TreeMap.java:1291)
at java.base/java.util.TreeMap.put(TreeMap.java:536)
at TreeMapDemo.main(TreeMapDemo.java:6)
重写compareTo方法:
@Override
public int compareTo(Person o) {
// TODO Auto-generated method stub
return this.getAge() - o.getAge();
}
put方法
public V put(K key, V value) {
// 把root节点给t
Entry<K,V> t = root;
// 如果根节点是null,那么这棵树是空树,新增的节点就是根节点。
if (t == null) {
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
// 构造器放入的比较器
Comparator<? super K> cpr = comparator;
// 比较器不为空,那么就优先使用比较器来进行比较
if (cpr != null) {
// 比较key值,找到目标位置
do {
// 将当前节点给parent
parent = t;
// 将比较结果给cmp
cmp = cpr.compare(key, t.key);
// 判断插入的key和当前节点(t)的大小
if (cmp < 0)
// 如果比当前节点小,当将前节点指向为左子树的根节点
t = t.left;
else if (cmp > 0)
t = t.right;
else
// 如果key相等,就将当前的value复制替换掉原来的value
return t.setValue(value);
} while (t != null);
}
// 比较器为null的情况下,使用Comparable接口的compareTo 方法来比较
else {
// 插入key 为null,抛异常
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
// 和上面的比较思路一样
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
// 创建Entry对象,并把parent对象放入
Entry<K,V> e = new Entry<>(key, value, parent);
// 插入节点
if (cmp < 0)
// 小于parent,插入左子树
parent.left = e;
else
// 插入右子树
parent.right = e;
// 调整红黑树结构,使其符合规则
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
不需要调整:
需要调整的情况:
/** From CLR */
private void fixAfterInsertion(Entry<K,V> x) {
// 默认插入新节点的颜色是红色
x.color = RED;
// 需要进行调整的条件
// 父亲节点颜色为红色
while (x != null && x != root && x.parent.color == RED) {
/* 分情况进行调整
x 表示当前节点,p表示parent节点,u表示uncle节点,g表示grandfather节点
o (g)
/ \
o(p) o(u)
o(x)
*/
// 如上图
if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
// y就是uncle节点
Entry<K,V> y = rightOf(parentOf(parentOf(x)));
// 如果uncle节点是红色
if (colorOf(y) == RED) {
// 重新染色
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
} else {
// uncle节点是黑色
// 判断当前节点的位置 如图:
/*
o (g)
/ \
o(p) o(u)
\
o(x)
*/
if (x == rightOf(parentOf(x))) {
x = parentOf(x);
// 左旋
rotateLeft(x);
}
// 重新染色
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
rotateRight(parentOf(parentOf(x)));
}
} else {
....// 原理相同
}
}
root.color = BLACK;
}
private void rotateLeft(Entry<K,V> p) {
// 如果参数节点不是NIL节点
if (p != null) {
// 获取p节点的右子节点
Entry<K,V> r = p.right;
// 将r的左子树设置为p 的右子树
p.right = r.left;
// ,则将p设置为r左子树的父亲
if (r.left != null)
r.left.parent = p;
// 将p 的父亲设置为r 的父亲
r.parent = p.parent;
// 如果p的父亲是null
if (p.parent == null)
root = r;
else if (p.parent.left == p)
p.parent.left = r;
else
p.parent.right = r;
// 将p设置为r的左子树,将r设置为p的父亲
r.left = p;
p.parent = r;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。