一、TreeMap
1.基本特征:二叉树、二叉查找树、二叉平衡树、红黑树
2.每个节点的结构由:key value left right parent color 六部分组成
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;//颜色,默认黑色
}
3.添加原理
从根节点开始比较,添加过程就是构造二叉平衡树的过程,会自动平衡,平衡离不开比较:外部比较器优先,然后是内部比较器。如果两个比较器都没有,就抛出异常
public V put(K key, V value) {
Entry<K,V> t = root;
//如果是第一个节点,则进入if
if (t == null) {
//即使是添加第一个节点,也要使用比较器
compare(key, key); // type (and possibly null) check
//创建根节点
root = new Entry<>(key, value, null);
//此时只有一个节点
size = 1;
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 //找到了对应的key,使用新的value覆盖旧的value
return t.setValue(value);
} while (t != null);
}
else {
//如果外部比较器没有,就使用内部比较器
....
}
//找到了要添加的位置,创建新节点加到树中
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
size++;
return null;
}
4.查询原理
public V get(Object key) {
//根据key找Entry
Entry<K,V> p = getEntry(key);
//如果Entry存在则返回value
return (p==null ? null : p.value);
}
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
//如果找到了,就返回Entry
return p;
}
//如果没有找到,就返回null
return null;
}
3.TreeMap主要的成员变量及其含义
public class TreeMap<K, V> implements NavigableMap<K, V> {
private final Comparator<? super K> comparator;//外部比较器
private transient Entry<K, V> root = null; //根节点
private transient int size = 0;//节点个数
public TreeMap() {
comparator = null;//没有指定外部比较器
}
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;//指定外部比较器
}
}
二、TreeSet
1.TreeSet的底层使用的是TreeMap,所以底层也是红黑树
2.TreeSet的元素e是存储在TreeMap的key中,value统一为同一个 Object对象
public class TreeSet<E> implements NavigableSet<E> {
//底层是TreeMap
private transient NavigableMap<E, Object> m;
private static final Object PRESENT = new Object();//同一个对象
public TreeSet() {
//创建TreeSet对象就是创建一个TreeMap对象
this(new TreeMap<E, Object>());
}
TreeSet(NavigableMap<E, Object> m) {
this.m = m;
}
public boolean add(E e) {
return m.put(e, PRESENT) == null;
}
public int size() {
return m.size();
}
}