java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > TreeMap源码分析

Java中的TreeMap底层源码分析

作者:爱喝咖啡的程序员

这篇文章主要介绍了Java中的TreeMap底层源码分析,TreeMap与Hashmap、LinkedHashMap不同,他的底层不再是数组,而是一颗红黑树,在插入、删除或者替换元素时,TreeMap能按照事先约定的顺序来对key进行排序和迭代查询,需要的朋友可以参考下

一. 基本原理和优缺点

TreeMap与Hashmap、LinkedHashMap不同,他的底层不再是数组,而是一颗红黑树。

在插入、删除或者替换元素时,TreeMap能按照事先约定的顺序来对key进行排序和迭代查询。

支持二叉搜索,因此做查询操作时,时间复杂度是O(logn),虽然比起纯粹使用数组要慢O(1),但是比普通的链表要快O(n)。

插入数据类似链表,只调整几个指针就实现插入操作。

TreeMap的缺点在于,为了使用红黑树,每次新增、删除、修改一个节点后,都需要重新调整整颗树,达到红黑树的要求,这个调整的过程可能涉及到变色,也可能涉及到左旋、右旋,所以耗时啊!

二. 源码分析

2.1 put(K key, V value)

TreeMap<Integer, String> map = new TreeMap<>();
map.put(2, "张三");
map.put(1, "李四");
map.put(3, "王五");
map.put(4, "赵六");

Treemap默认使用key的升序排序,如果遍历上方的map,能获取到1->2->3->4排列顺序的key-value对。

我们也可以自定义比较key的方法,具体的做法如下:

Map<Integer, String> map = new TreeMap<Integer, String>(new Comparator<Integer> () {
	@Override
	public int compare(Integer o1, Integer o2) {
		return o2 - o1;
	}
}) {};

此时,再次遍历map,能获取到4->3->2->1排列顺序的key-value对。

我们可以把TreeMap put( )方法的源码分解成几个部分。

首先,判断当前TreeMap有没有节点,如果连一个节点都没有,那好办,就拿着本次待新增的k-v,做成一个节点,此时红黑树只有一个节点。

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;
}

接着,将待插入的key与根节点对应的key进行比较,这里就可以自定义比较方式了。

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);
}

上图中这么大一坨代码,无非就是列举了两种情况,如果没有显示的给出Comparator,则使用key的compareTo()方法比较大小。如果给出了显示的Comparator,则使用自定义的compare()方法进行比较。

然后,把较小的节点挂到根节点的左边,把较大的节点挂到根节点的右边。这不就是二叉搜索树的概念么。

if (cmp < 0)
	parent.left = e;
else
	parent.right = e;

最后,使用红黑树相关的算法,利用变色啊、旋转啊等手段,使添加了节点的二叉搜索树重新成为红黑树。

fixAfterInsertion(e);

2.2 红黑树节点的结构

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

到此这篇关于Java中的TreeMap底层源码分析的文章就介绍到这了,更多相关TreeMap源码分析内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文