mac_girl

TreeMap的源码学习

TreeMap的源码学习

一)、TreeMap的特点

根据key值进行排序。

二)、按key值排序的两种排序算法实现

1).在构造方法中传入比较器

public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}

比较器comparator实现Comparator接口,实现compare(T o1, T o2)方法;

int compare(T o1, T o2);

2).key值实现Comparable接口,重写 compareTo(key k)方法

T implements Comparable{
@override
public int compareTo(T k)
}

注: 对于TreeMap而言,排序是一个必须进行的过程,要正常使用TreeMap必须制 定排序规则,加入Comparator或key对象实现Comparable接口,若没有制定 比较规则则会抛出java.lang.ClassCastException。

因为String对象默认实现了Comparable接口,实现了comparaTo方法,使用String类型作为key值,不用进行排序。

三)、TreeMap的数据结构

红黑树:Entry<k, v>

Entry<k ,v> 对象的属性:

K key;
V value;
Entry<k, v> left;
Entry<k, v> right;
Entry<k, v> parent;
boolean color = BLACK;

红黑树是一种平衡查找树.

四)、TreeMap的主要属性

//比较器
private final Comparator<? super K> comparator;
//树的根节点
private transient Entry<K,V> root;
//节点个数即元素个数
private transient int size = 0;
//修改次数
private transient int modCount = 0;
//用于构造红黑树
private static final boolean RED = false;
private static final boolean BLACK = true;

五)、TreeMap的put(K key, V value)方法

步骤:

1).获取root节点,判断是否第一次添加元素 ,若是第一次添加元素则将该元素设为根节点。

2).如若不是第一次添加,根据key值,调用比较规则从根节点开始比较左右子树直至到达叶子节点,根据key的比较结果决定放置到叶子节点的左树位置或右树位置,> 0放置右树, < 0 放置右树。

3).fixAfterInsertion修改插入元素后树的结构,转为红黑树。

TreeMap<String, String> treeMap = new TreeMap<>();
treeMap.put("a","v");

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;
modCount++;
return null;
}
//根据排序规则将元素插入到树结构中
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
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);
}
//使用key 实现Comparable的compareTo()规则
else {
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
/**
如果Key没有加入比较器或没有实现Comparable这里就
抛出java.lang,ClassCastException
*/
Comparable<? super K> k = (Comparable<? super K>) key;
//一直比较左右子树的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);
}
//根据返回的比较结果决定插入节点的位置
Entry<K,V> e = new Entry<>(key, value, parent);
//< 0 作为节点的左子树
if (cmp < 0)
parent.left = e;
// > 0 作为节点的右子树
else
parent.right = e;
//调整插入元素的树结构,转为红黑树
fixAfterInsertion(e);
size++;
modCount++;
return null;
}

六)、TreeMap的get(K key)方法

步骤:

1).获取根节点

2).从根节点开始比较左右子树的key值

3).若树中某一节点的key值与查找的key值相等,则返回对应的Entry<k, v>对象

treeMap.get("a");

public V get(Object key) {
Entry<K,V> p = getEntry(key);
return (p==null ? null : p.value);
}

final Entry<K,V> getEntry(Object key) {
// Offload comparator-based version for sake of performance
//判断是否存在比较器,若有比较器,则使用比较器的比较规则
if (comparator != null)
return getEntryUsingComparator(key);
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
//没有比较器使用comparale的compareTo()规则
Comparable<? super K> k = (Comparable<? super K>) key;
Entry<K,V> p = root;
//从根节点遍历左右子树,若key值相等,则返回当前节点对象
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的功能比HashMap的功能强大, 实现了sortedMap接口,可以对元素 进行排序,单TreeMap的性能却略低于HashMap,当需要对集合进行排序操作可使用TreeMap.

posted on 2019-10-12 11:26  宇宙美少女  阅读(175)  评论(0)    收藏  举报

导航