概述
TreeMap实现了SortedMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序, 也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。 如果需要一个按键排序的map,建议使用TreeMap。 在使用 TreeMap 时,key 必须实现 Comparable 接口或者在构造 TreeMap 传入自定义的 Comparator,否则会抛java.lang.ClassCastException 类型的异常。
数据结构
TreeMap底层是基于红黑树实现的,红黑树是一种自平衡的二叉查找树,对插入的元素按顺序存储,红黑树在最坏的情况下也能保持良好的性能,查找、插入和删除操作的时间复杂度均为 O(logn)。想了解红黑树的可通过可视化网站先了解一下:红黑树可视化。
构造方法
无参构造方法:
public TreeMap() {
this.comparator = null;
}
可自定义排序规则的构造方法,TreeMap默认是按升序排序的,在构造方法中传入Comparator.reverseOrder()可以使TreeMap按降序排序。
public TreeMap(Comparator<? super K> var1) {
this.comparator = var1;
}
带有Map参数的构造方法,可将如HashMap之类的Map集合元素插入TreeMap进行排序:
public TreeMap(Map<? extends K, ? extends V> var1) {
this.comparator = null;
this.putAll(var1);
}
基本方法
添加元素put(),向红黑树中添加一个节点,可能会破坏红黑树的平衡性,fixAfterInsertion()方法可以对添加节点后的红黑树进行重平衡操作。
public V put(K var1, V var2) {
TreeMap.Entry var3 = this.root;
if (var3 == null) {
this.compare(var1, var1);
this.root = new TreeMap.Entry(var1, var2, (TreeMap.Entry)null);
this.size = 1;
++this.modCount;
return null;
} else {
Comparator var6 = this.comparator;
int var4;
TreeMap.Entry var5;
if (var6 != null) {
do {
var5 = var3;
var4 = var6.compare(var1, var3.key);
if (var4 < 0) {
var3 = var3.left;
} else {
if (var4 <= 0) {
return var3.setValue(var2);
}
var3 = var3.right;
}
} while(var3 != null);
} else {
if (var1 == null) {
throw new NullPointerException();
}
Comparable var7 = (Comparable)var1;
do {
var5 = var3;
var4 = var7.compareTo(var3.key);
if (var4 < 0) {
var3 = var3.left;
} else {
if (var4 <= 0) {
return var3.setValue(var2);
}
var3 = var3.right;
}
} while(var3 != null);
}
TreeMap.Entry var8 = new TreeMap.Entry(var1, var2, var5);
if (var4 < 0) {
var5.left = var8;
} else {
var5.right = var8;
}
this.fixAfterInsertion(var8);//重平衡
++this.size;
++this.modCount;
return null;
}
}
查找元素get(),红黑树的查找和普通二叉树的查找并没有什么区别。
public V get(Object var1) {
TreeMap.Entry var2 = this.getEntry(var1);
return var2 == null ? null : var2.value;
}
final TreeMap.Entry<K, V> getEntry(Object var1) {
if (this.comparator != null) {
return this.getEntryUsingComparator(var1);
} else if (var1 == null) {
throw new NullPointerException();
} else {
Comparable var2 = (Comparable)var1;
TreeMap.Entry var3 = this.root;
while(var3 != null) {
int var4 = var2.compareTo(var3.key);
if (var4 < 0) {
var3 = var3.left;
} else {
if (var4 <= 0) {
return var3;
}
var3 = var3.right;
}
}
return null;
}
}
删除元素remove(),从红黑树中删除一个节点,也可能会破坏红黑树的平衡性,fixAfterDeletion()方法可以对删除节点后的红黑树进行重平衡操作。
public V remove(Object var1) {
TreeMap.Entry var2 = this.getEntry(var1);
if (var2 == null) {
return null;
} else {
Object var3 = var2.value;
this.deleteEntry(var2);
return var3;
}
}
private void deleteEntry(TreeMap.Entry<K, V> var1) {
++this.modCount;
--this.size;
TreeMap.Entry var2;
if (var1.left != null && var1.right != null) {
var2 = successor(var1);
var1.key = var2.key;
var1.value = var2.value;
var1 = var2;
}
var2 = var1.left != null ? var1.left : var1.right;
if (var2 != null) {
var2.parent = var1.parent;
if (var1.parent == null) {
this.root = var2;
} else if (var1 == var1.parent.left) {
var1.parent.left = var2;
} else {
var1.parent.right = var2;
}
var1.left = var1.right = var1.parent = null;
if (var1.color) {
this.fixAfterDeletion(var2);
}
} else if (var1.parent == null) {
this.root = null;
} else {
if (var1.color) {
this.fixAfterDeletion(var1);
}
if (var1.parent != null) {
if (var1 == var1.parent.left) {
var1.parent.left = null;
} else if (var1 == var1.parent.right) {
var1.parent.right = null;
}
var1.parent = null;
}
}
}
适用场景
TreeMap是一种有序的映射,它可以在保证高效性的同时,提供一些基于排序的操作。因此,TreeMap适用于以下场景:
- 需要按照键的自然顺序或者指定的比较器进行排序的场景,例如字典,排行榜,日程安排等。
- 需要快速找到映射中最小或者最大的键或者值的场景,例如优先队列,堆,区间查询等。
- 需要快速找到映射中某个范围内的所有键或者值的场景,例如范围搜索,前缀匹配,区间统计等。