注意:本文基于JDK1.8进行记录。
1 简介
不允许插入key值相同的元素,定制排序允许插入null的key值,自然排序不允许插入null的key值。
底层是红黑树,支持自然排序和定制排序。自然排序要求key值实现Comparable接口,定制排序要求创建TreeMap时传入Comparator对象。
线程不安全。
2 方法说明
2.1 构造方法
// 空参构造器。
public TreeMap();
// 指定比较器的构造器。
public TreeMap(Comparator<? super K> comparator);
// 传入了一个集合的构造器,集合没有比较器,添加指定集合。
public TreeMap(Map<? extends K, ? extends V> m);
// 传入了一个集合的构造器,集合提供比较器,添加指定集合。
public TreeMap(SortedMap<K, ? extends V> m);
2.2 常用方法
// 根据key获取value,不存在会返回null。
public V get(Object key);
// 设置key和value键值对,返回原value,不存在会返回null。
public V put(K key, V value);
// 根据key删除键值对,返回原value,不存在会返回null。
public V remove(Object key);
3 源码分析
3.1 属性
// 自定义的比较器,用于排序。
private final Comparator<? super K> comparator;
// 红黑树的根节点。
private transient Entry<K,V> root;
// 节点个数。
private transient int size = 0;
// 修改次数,用于快速失败机制。
private transient int modCount = 0;
3.2 构造方法
// 空参构造器。
public TreeMap() {
comparator = null;
}
// 指定比较器的构造器。
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
// 传入了一个集合的构造器,集合没有比较器,添加指定集合。
public TreeMap(Map<? extends K, ? extends V> m) {
comparator = null;
putAll(m);
}
// 传入了一个集合的构造器,集合提供比较器,添加指定集合。
public TreeMap(SortedMap<K, ? extends V> m) {
comparator = m.comparator();
try {
buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
} catch (java.io.IOException cannotHappen) {
} catch (ClassNotFoundException cannotHappen) {
}
}
3.3 常用方法
// 根据key获取value,不存在会返回null。
public V get(Object key) {
// 根据key查询节点。
Entry<K,V> p = getEntry(key);
return (p==null ? null : p.value);
}
// 根据key查询节点。
final Entry<K,V> getEntry(Object key) {
// 比较器存在,则使用比较器获取节点。
if (comparator != null)
return getEntryUsingComparator(key);
// 比较器不存在,并且key值为null,则抛异常。
if (key == null)
throw new NullPointerException();
// 比较器不存在,则使用key值比较。
Comparable<? super K> k = (Comparable<? super K>) key;
// 保存红黑树的根节点。
Entry<K,V> p = root;
// 根节点不为空,则查询红黑树并比较。
while (p != null) {
int cmp = k.compareTo(p.key);
if (cmp < 0)
p = p.left;
else if (cmp > 0)
p = p.right;
else
return p;
}
return null;
}
// 使用比较器查询key值对应的节点。
final Entry<K,V> getEntryUsingComparator(Object key) {
// 保存key值。
K k = (K) key;
// 保存比较器。
Comparator<? super K> cpr = comparator;
// 比较器存在,使用比较器查询。
if (cpr != null) {
// 保存红黑树的根节点。
Entry<K,V> p = root;
// 根节点不为空,则查询红黑树并比较。
while (p != null) {
// 使用比较器的比较方法。
int cmp = cpr.compare(k, p.key);
if (cmp < 0)
p = p.left;
else if (cmp > 0)
p = p.right;
else
return p;
}
}
return null;
}
// 设置key和value键值对,返回原value,不存在会返回null。
public V put(K key, V value) {
// 保存红黑树的根节点。
Entry<K,V> t = root;
// 根节点为空,则设置根节点。
if (t == null) {
// 类型检查。
compare(key, key);
// 创建根节点。
root = new Entry<>(key, value, null);
// 节点大小设置为1。
size = 1;
// 操作数自增。
modCount++;
// 返回null。
return null;
}
// 定义比较的结果。
int cmp;
// 定义父节点。
Entry<K,V> parent;
// 保存比较器。
Comparator<? super K> cpr = comparator;
// 比较器存在,使用比较器查询并设置键值对。
if (cpr != null) {
// 使用比较器逐个比较节点。
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);
}
// 比较器不存在,使用key值比较查询并设置键值对。
else {
// 如果key值为null,则抛异常。
if (key == null)
throw new NullPointerException();
// 使用key值比较。
Comparable<? super K> k = (Comparable<? super K>) key;
// 使用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<K,V> e = new Entry<>(key, value, parent);
// 比较的结果小于0,新节点作为父节点的左节点。
if (cmp < 0)
parent.left = e;
// 比较的结果大于0,新节点作为父节点的右节点。
else
parent.right = e;
// 节点插入后,调整红黑树的高度和颜色。
fixAfterInsertion(e);
// 个数自增。
size++;
// 操作数自增。
modCount++;
// 返回null。
return null;
}
// 根据key删除键值对,返回原value,不存在会返回null。
public V remove(Object key) {
// 根据key查询节点。
Entry<K,V> p = getEntry(key);
// 节点为null,返回null。
if (p == null)
return null;
// 节点不为null,删除节点。
V oldValue = p.value;
deleteEntry(p);
return oldValue;
}