本文作者:黄海燕,叩丁狼高级讲师。原创文章,转载请注明出处。
##前言
之前很多小伙伴问我怎么看源代码,还有就是越来越多的程序员都想要看源代码,搞懂底层原理,但是感觉源代码非常的晦涩难懂,不够直接和清晰,所以我希望这篇文章能够快速带同学们看懂java源码,更加深入的学习java,帮助小伙伴们节约学习的时间成本.
##1.树的介绍
- 什么是树结构?其实就是一个节点下面有多个子节点,我们称之为树结构,如下图:
- 普通节点:拥有子节点的节点。
- 叶子节点:没有子节点的节点。
什么是二叉树?
- 二叉树就是一个节点最多只能有2个子节点,分为左节点和右节点,如下图:
什么是排序二叉树?
- 若左子树不为空,则左子树所有节点的值小于根节点的值。
- 若右子树不为空,则右子树所有节点的值大于根节点的值。
如图:
什么是红黑树?
红黑树其实是一个平衡排序二叉树,属于查询高效的树结构.请看下图:
查询元素6普通的二叉树需要操作6次,红黑树只需要操作4次,所以红黑树查询更加高效.
##1.TreeMap的结构介绍
###1.1 结构关系
public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable{
继承关系:
- 父类AbstractMap,让子类拥有基本Map的方法,比如增(put)删(remove)查(get)等方法.
实现关系:
- NavigableMap:父接口为SortedMap,所以NavigableMap为可排序接口,表示TreeMap但是一个排序的Map:
- Cloneable:标记型的接口,内部都没有方法和属性,实现 Cloneable来表示该对象能被克隆,能使用Object.clone()方法。如果没有实现 Cloneable的类对象调用clone()就会抛出CloneNotSupportedException。
- Serializable:标记型的接口,内部都没有方法和属性,实现Serializable表示可进行序列化和反序列化,表示能够使用在ObjectOutputStream.writeObject())和ObjectInputStream.readObject()
###1.2 基本成员组成
/**
* 比较器:类似于一个"裁判",用于比较插入对象和树节点的内容大小
* 因为TreeMap是一个红黑树,红黑树是一个排序二叉树,插入元素的时候需要进行排序,排序可以使用比较器中的方式排序
*/
private final Comparator<? super K> comparator;
/**
* 根节点
*/
private transient Entry<K,V> root;
/**
* 树的元素个数
*/
private transient int size = 0;
/**
* 操作次数:增加和删除操作数都会加1,用于控制并发修改异常
*/
private transient int modCount = 0;
通过root根节点可以看出一个节点(元素)就是一个Entry对象,所以一个节点(元素)中包含多个数据.结构如下:
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;//颜色
节点表示如下:
###1.3添加操作:
public V put(K key, V value) {
Entry<K, V> t = root;//和插入节点进行比较的树节点
//根节点为空
if (t == null) {
compare(key, key); //key比key,自己比较自己,目的是想要检查类型,确保传入了比较器或者是key实现了可比较接口
//创建了一个没有父节点的新的节点,作为根节点
root = new Entry<>(key, value, null);
size = 1;//元素个数为1
modCount++;//操作数+1
return null;//返回空,根节点添加结束
}
int cmp;//表示比较结果
Entry<K, V> parent;
// cpr临时表示比较器
Comparator<? super K> cpr = comparator;
if (cpr != null) {//比较器不为空,就使用比较器比较元素
do {
parent = t;//父节点为t
cmp = cpr.compare(key, t.key);//通过比较器对key和树节点比较得到比较结果
if (cmp < 0)//比较结果小于0,表示插入的元素比树节点小
t = t.left;//t往左走
else if (cmp >