(接上文《源码阅读(21):Java中其它主要的Map结构——TreeMap容器(1)》)
(注:笔者翻阅了一下网络上的相关资料,基本上没有发现把TreeMap容器的删除操作讲清楚的文章)
2.3、TreeMap添加操作
TreeMap同样使用put方法进行新的K-V键值对对象的添加操作,其工作过程完全参照之前已经介绍过的红黑树添加新结点的方式进行工作(可参考之前的一篇文章《源码阅读(17):红黑树在Java中的实现和应用》),简单来TreeMap容器添加新的结点有两个关键步骤:
- 通过堆树的方式找到适合的结点,将新的结点添加成前者的左叶子结点或者右叶子节点。
- 由于以上的添加操作,红黑树可能会失去平衡性,于是就需要进行操作让红黑树重新平衡。
清楚了以上两个关键步骤,我们可以详细阅读put方法的源代码了:
// 实际上整个put方法中的代码都在处理第一个步骤;
// put方法中调用的fixAfterInsertion方法,是在处理第二个步骤
public V put(K key, V value) {
Entry<K,V> t = root;
// 当这个条件成立,就代表当前红黑树为null
if (t == null) {
// 这个情况下,还需要进行compare操作,主要是保证当前红黑树使用的compare比较器,针对当前出入的key是有效的
// 另外一个作用是为了在使用key自带的compare比较器时,key信息不为null
compare(key, key); // type (and possibly null) check
// 创建一个root结点对象,修改modCount代表的操作次数
// 然后添加操作就成功结束
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
// comparator对象是TreeMap容器实例化是设定的比较器,根据前文中对TreeMap容器的实例化过程描述来看
// comparator比较器对象可能为null
Comparator<? super K> cpr = comparator;
// 如果comparator比较器不为空,那么寻找添加位置的操作就基于这个比较器进行
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
// 如果条件成立,就说明将要添加的结点信息的权值,小于当前比较的红黑树中结点的权值
// 则向t结点的左儿子寻找添加位置
if (cmp < 0)
t = t.left;
// 如果条件成立,说明将要添加的结点信息的权值,大于当前比较的红黑树中结点的权值
else if (cmp > 0)
t = t.right;
// 如果条件成立,就说明将要添加的结点信息的权值,等于当前比较的红黑树中结点的权值
// 添加操作就变成了修改操作
else
return t.setValue(value);
} while (t != null);
}
// 如果comparator比较器为null,那么寻找添加位置的操作就基于key自带的comparator比较器
// 其寻找添加位置的逻辑和以上条件代码块的逻辑相同,这里就不再赘述了
else {
if (key