概述
TreeMap 是 Java 集合框架中的一种有序映射(键值对)实现,它基于红黑树数据结构来维护元素的有序性。
关键代码
public class TreeMap<K,V> extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable {
// 内部节点类,继承自红黑树的节点基类
private 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;
boolean color = BLACK;
}
// 红黑树根节点
private transient Entry<K,V> root;
// 比较器
private final Comparator<? super K> comparator;
// ...
// 插入节点并进行平衡操作
private Entry<K,V> putVal(K key, V value) {
// 插入节点的过程类似于普通的二叉搜索树插入
Entry<K,V> t = root;
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;
// ...
// 进行红黑树的平衡操作
fixAfterInsertion(x);
return null;
}
// 红黑树的插入平衡操作
private void fixAfterInsertion(Entry<K,V> x) {
x.color = RED;
while (x != null && x != root && x.parent.color == RED) {
// ...
}
root.color = BLACK;
}
// ...
// 获取指定键的节点
final Entry<K,V> getEntry(Object key) {
if (comparator != null)
return getEntryUsingComparator(key);
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
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;
}
// ...
}
TreeMap 设计思想和应用场景
设计思想:
- 有序性维护:
TreeMap通过使用红黑树这种自平衡二叉搜索树的数据结构,可以保持元素的有序性。红黑树的平衡性能够确保在插入、删除元素时,树的高度不会过高,从而保证了操作的时间复杂度稳定在 O(log N)。 - 二叉搜索树:
TreeMap的底层数据结构是一棵二叉搜索树(BST)。这种树结构使得在查找、插入和删除元素时能够迅速定位到目标节点,提高了操作的效率。 - 平衡性维护: 红黑树作为一种自平衡的二叉搜索树,在插入和删除操作时能够通过旋转和重新着色来保持树的平衡,避免了出现极端不平衡的情况,从而保证了较稳定的性能。
应用场景:
- 有序数据存储: 当需要存储有序的键值对数据时,
TreeMap是一个很好的选择。它能够保持元素的有序性,使得元素可以按照键的顺序进行迭代和访问。 - 范围查询:
TreeMap支持范围查询操作,可以很方便地获取某个范围内的键值对。例如,找到大于等于某个键的最小键值对,或者找到小于等于某个键的最大键值对。 - 按照优先级处理: 在某些场景中,需要按照优先级或权重来处理元素。
TreeMap可以根据键的比较来实现这种有序的处理方式。 - LRU 缓存:
TreeMap可以用来实现 LRU(最近最少使用)缓存,通过在每次访问元素时将其移动到树的末尾,从而实现缓存的自动淘汰。