1、简述
- 今天我们来介绍下 TreeMap,TreeMap 是基于红黑树结构实现的一种 Map。
- 那什么又是红黑数呢?
- (1)每个节点必须是红色或者黑色;
- (2)根节点是黑色;
- (3)每个叶子节点(NIL 节点,空节点)是黑色的;
- (4)如果一个节点是红色的,则它两个字节点都是黑色的,也就是说在一条路径上不能出现相邻的两个红色节点;
- (5)从任一节点到每个叶子的所有路径都包含相同数目的黑色节点。
- 如何保持红黑树特性?
- 每当添加或删除节点后,红黑树就发生了变化,可能不再满足上述五种特性,所以为了保持红黑树以上特性,就需要三个动作:左旋、右旋、着色。
2、归纳
- 继承了 AbstractMap,实现了 NavigableMap 接口,所以支持一系列的导航方法,实现了 Cloneable 和 Serializable 接口,所以支持复制(拷贝)、序列化。
- 可在构造函数传入自己的比较器。
- 其底层是基于红黑树实现的,无序,不可重复,不允许 null 键,但允许 null 值存在。
- 单线程安全,多线程不安全。
3、分析
3.1、接口
- 在分析 TreMap 源码之前,我们先来看看集合的接口 Map。
public interface Map<K, V> {
...
V put(K key, V value);
V remove(Object key);
V get(Object key);
...
}
- 在上述接口中,我只抽取了比较重要的几个方法,然后以此为后续重点分析目标,其 Map 接口对应的源码中远不止上述几个方法,有兴趣的同学可以自行翻阅。
3.2、静态内部类
public class TreeMap<K, V> extends AbstractMap<K, V>
implements NavigableMap<K, V>, Cloneable, java.io.Serializable {
...
static final class TreeMapEntry<K, V> implements Map.Entry<K, V> {
K key;
V value;
TreeMapEntry<K, V> left;
TreeMapEntry<K, V> right;
TreeMapEntry<K, V> parent;
boolean color = BLACK;
TreeMapEntry(K key, V value, TreeMapEntry<K, V> parent) {
this.key = key;
this.value = value;
this.parent = parent;
}
...
}
...
}
3.3、成员变量
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 TreeMapEntry<K, V> root;
private transient int size = 0;
private transient int modCount = 0;
...
}
3.4、构造函数
public class TreeMap<K, V> extends AbstractMap<K, V>
implements NavigableMap<K, V>, Cloneable, java.io.Serializable {
...
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.5、增操作
public class TreeMap<K, V> extends AbstractMap<K, V>
implements NavigableMap<K, V>, Cloneable, java.io.Serializable {
...
public V put(K key, V value) {
TreeMapEntry<K, V> t = root;
if (t == null) {
compare(key, key);
root = new TreeMapEntry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
TreeMapEntry<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);
} else {
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) 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);
}
TreeMapEntry<K, V> e = new TreeMapEntry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
private void fixAfterInsertion(TreeMapEntry<K, V> x) {
x.color = RED;
while (x != null && x != root && x.parent.color == RED) {
if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
TreeMapEntry<K, V> y = rightOf(parentOf(parentOf(x)));
if (colorOf(y) == RED) {
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
} else {
if (x == rightOf(parentOf(x))) {
x = parentOf(x);
rotateLeft(x);
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
rotateRight(parentOf(parentOf(x)));
}
} else {
TreeMapEntry<K, V> y = leftOf(parentOf(parentOf(x)));
if (colorOf(y) == RED) {
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
} else {
if (x == leftOf(parentOf(x))) {
x = parentOf(x);
rotateRight(x);
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
rotateLeft(parentOf(parentOf(x)));
}
}
}
root.color = BLACK;
}
...
}
3.6、删操作
public class TreeMap<K, V> extends AbstractMap<K, V>
implements NavigableMap<K, V>, Cloneable, java.io.Serializable {
...
public V remove(Object key) {
TreeMapEntry<K, V> p = getEntry(key);
if (p == null)
return null;
V oldValue = p.value;
deleteEntry(p);
return oldValue;
}
private void deleteEntry(TreeMapEntry<K, V> p) {
modCount++;
size--;
if (p.left != null && p.right != null) {
TreeMapEntry<K, V> s = successor(p);
p.key = s.key;
p.value = s.value;
p = s;
}
TreeMapEntry<K, V> replacement = (p.left != null ? p.left : p.right);
if (replacement != null) {
replacement.parent = p.parent;
if (p.parent == null)
root = replacement;
else if (p == p.parent.left)
p.parent.left = replacement;
else
p.parent.right = replacement;
p.left = p.right = p.parent = null;
if (p.color == BLACK)
fixAfterDeletion(replacement);
} else if (p.parent == null) {
root = null;
} else {
if (p.color == BLACK)
fixAfterDeletion(p);
if (p.parent != null) {
if (p == p.parent.left)
p.parent.left = null;
else if (p == p.parent.right)
p.parent.right = null;
p.parent = null;
}
}
}
...
}
3.7、查操作
public class TreeMap<K, V> extends AbstractMap<K, V>
implements NavigableMap<K, V>, Cloneable, java.io.Serializable {
...
public V get(Object key) {
TreeMapEntry<K, V> p = getEntry(key);
return (p == null ? null : p.value);
}
final TreeMapEntry<K, V> getEntry(Object key) {
if (comparator != null)
return getEntryUsingComparator(key);
if (key == null)
throw new NullPointerException();
Comparable<? super K> k = (Comparable<? super K>) key;
TreeMapEntry<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;
}
...
}