![6dabe0fdff43b3378c537098ad1e3e93.png](https://i-blog.csdnimg.cn/blog_migrate/e842921db6cab4c729662572fa536452.jpeg)
TreeMap是红黑二叉树的典型实现。我们打开TreeMap的源码,发现里面有一行核心代码:
private transient Entry<K,V> root = null;
root用来存储整个树的根节点。我们继续跟踪Entry(是TreeMap的内部类)的代码:
![4bef4a102c724c5d33ed7d02ba316a4d.png](https://i-blog.csdnimg.cn/blog_migrate/b98ecba8f680536bd7b44764b982c725.jpeg)
可以看到里面存储了本身数据、左节点、右节点、父节点、以及节点颜色。 TreeMap的put()/remove()方法大量使用了红黑树的理论。本书限于篇幅,不再展开。需要了解更深入的,可以参考专门的数据结构书籍。
TreeMap和HashMap实现了同样的接口Map,因此,用法对于调用者来说没有区别。HashMap效率高于TreeMap;在需要排序的Map时才选用TreeMap。
1、TreeMap的用法
import java.util.Comparator;
import java.util.TreeMap;
public class TestTreeMap {
public static void main(String[] args) {
//无参构造
// TreeMap tree = new TreeMap();
//创建外比较器对象,定义比较规则
Comparator com = new ComparaStringLength();
TreeMap tree = new TreeMap(com);
tree.put("hello1", 123);
tree.put("world11", 456);
tree.put("hello", 321);
tree.put("java", 789);
System.out.println("元素的个数:" + tree.size());
System.out.println(tree);
}
}
class ComparaStringLength implements Comparator{
/**
* 比较规则:根据字符串的长度进行比较
*/
@Override
public int compare(Object o1, Object o2) {
String s1 = (String)o1;
String s2 = (String)o2;
return s1.length() - s2.length();
}
}
2、JDK源码分析
private final Comparator<? super K> comparator;//外部比较器
private transient Entry<K,V> root;//树根
(1)TreeMap()方法
public TreeMap() {
comparator = null;
}
(2)put(K key, V value)方法
public V put(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;//长度+1
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;//父节点
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;//null
if (cpr != null) {//如果外部比较器!=null,说明外部比较器存在
do {
parent = t;//把root赋给父节点
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;//root赋给父节点
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);
if (cmp < 0)
parent.left = e;//添加到左子树
else
parent.right = e;//添加到右子树
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
(3)TreeMap(Comparator<? super K> comparator)方法
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
注意:
如果使用TreeMap存储自定义对象做为key时,要求必须具备比较规则。
尚学堂百战程序员
百战程序员_IT6000集_影响6000万学习IT的中国人【官网】