前提:阅读本文最好对红黑树有基本的了解
介绍
- 扩展AbstractMap类并实现NavigatebleMap接口
- 访问和检索时间相当短,这使得TreeMap成为存储需要快速找到的大量排序信息的绝佳选择
- 树实现
- 适用于按自然顺序或自定义顺序遍历键(key)
- 不允许键为Null
- 非线程安全
- 具有fail-fast机制
继承关系 继承类介绍
AbstractMap:继承AbstractMap,它实现了Map接口,提供了Map接口的基本实现
NavigableMap:该接口继承自SortedMap接口,它的所有方法都是为定位设计的
变量解析(所有代码都不是完整的源码,而是精简过后的源码!结合源码食用更佳)
//比较器 用于维护映射的顺序 为null键使用自然排序
private final Comparator<? super K> comparator;
//红黑树根节点
private transient Entry<K,V> root;
//数据实际数量
private transient int size = 0;
//结构被修改次数
private transient int modCount = 0;
源码解析 常用方法解析
TreeMap.Entry
红黑树数据结构
static final class Entry<K,V> implements Map.Entry<K,V> {
K key;
V value;
//左节点
Entry<K,V> left;
//右节点
Entry<K,V> right;
//父节点
Entry<K,V> parent;
//节点颜色 root节点为黑色
boolean color = BLACK;
put(K key, V value)
作用:将指定值与指定键关联
public V put(K key, V value) {
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;
//判断是否有比较器 默认为null 可在构造函数中设置
if (cpr != null) {
//使用比较器的compare方法比较key应该在left节点还是right节点
//通过循环获取对应left或right节点的最后一个节点parent(当parent的下一个节点left/right为null时循环结束)
//else中的判断也是一样的 区别在于if中使用的是自定义比较器 else中使用的是自然排序
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
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);
}
//构建节点 通过上面的循环已经拿到parent节点
Entry<K,V> e = new Entry<>(key, value, parent);
//最后不管你的比较器(自然排序还是自定义的比较器)是什么 它只使用结果 将新节点链接到对应的left或right节点后
if (cmp < 0)
parent.left = e;
else
parent.right = e;
//维护此树的特性(修改节点颜色或左旋右旋等操作)以保证其成为红黑树
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
remove(Object key)
作用:从树的映射中删除键对应的映射
//从根节点开始遍历 获取对应的节点
Entry<K,V> p = getEntry(key);
if (p == null)
return null;
//获取value用于返回
V oldValue = p.value;
//删除此节点 重新维护此红黑树结构
deleteEntry(p);
return oldValue;
replace(K key, V value)
作用:替换指定键映射的值
//从根节点开始遍历 获取对应的节点
Entry<K,V> p = getEntry(key);
if (p!=null) {
V oldValue = p.value;
//替换旧值
p.value = value;
return oldValue;
}
return null;
}
get(Object key)
作用:返回指定键映射到的值
//从根节点开始遍历 获取对应的节点
Entry<K,V> p = getEntry(key);
return (p==null ? null : p.value);