文章目录
一、TreeMap概述
TreeMap是按照Key的排序结果组织内部结构的Map集合, 它改变了Map 类散乱无序的形象. 在 Key 有排序要求的场景下,使用TreeMap可以事半功倍. 在集合框架图中,ConcurrentHashMap、HashMap和TreeMap都继承于AbstractMap抽象类,他们的关系如图所示:
在TreeMap 的接口继承树中,有两个与众不同的接口: SortedMap 和 NavigableMap。SortedMap 接口表示它的Key 是有序不可重复的,支持获取头尾Key-Value 元素,或者根据Key指定范围获取子集合等。插入的Key必须实现Comparable 或提供额外的比较器Comparator,所以Key不允许为null,但是Value 可以。
二、TreeMap添加使用案例
NavigableMap 接口继承了 SortedMap 接口,根据指定的搜索条件返回最匹配的Key-Value 元素。不同于HashMap,TreeMap并非一定要覆写hashCode 和 equals 方法来达到key 去重的目的.
public class TreeMapRepeat {
public static void main(String[] args) {
// 如果仅把此处的TreeMap换成HashMap 的话,此处size=1;
TreeMap map = new TreeMap();
}
}
class Key implements Comparable<Key>{
@Override
// 返回负的常数,表示此对象永远小于输入的other对象,此处决定TreeMap 的 size=2
public int compareTo(Key other) {
return -1;
}
// hash是相等的
@Override
public int hashCode() {
return 1;
}
// equals 比较也是相等的
@Override
public boolean equals(Object obj) {
return true;
}
}
上述示例中的TreeMap 换成 HashMap, size 的结果则从2变成1. 注意HashMap 是使用hashCode 和 equals 实现去重的. 而TreeMap 依靠 Comparable 或Comparator 来实现Key的去重. 如果没有覆盖正确的方法,那么TreeMap 的最大特性将无法发挥出来, 甚至在运行时会出现异常. 如果要用TreeMap对Key进行排序,调用如下方法:
final int compare(Object k1, Object k2){
return comparator == null
? ((Comparable<? super K> k1).compareTo((K)k2))
: comparator.compara((K)k1, (K)k2);
}
如果Comparator 不为null,优先使用比较器 comparator 的compara 方法; 如果为null ,则使用Key 实现的自然排序 Comparable 接口的comparaTo 方法.如果两者都不满足,则抛出ClassCastException 异常.
三、红黑树实现TreeMap源码解析
基于红黑树实现的 TreeMap 提供了平均和最坏复杂度均为O(logn) 的增删改查操作,并且实现了NavigableMap 接口,该集合最大的特点是Key 的有序性. 先从类名和属性开始分析:
3.1 类名和属性源码解析
public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable
{
// 排序使用的比较器
private final Comparator<? super K> comparator;
// 根节点
private transient Entry<K,V> root;
...
// 定义成为有字面含义的常量
private static final boolean RED = false;
private static final boolean BLACK <