Java中的TreeMap底层源码分析

 更新时间:2023年12月15日 08:30:48   作者:爱喝咖啡的程序员  
这篇文章主要介绍了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源码分析内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mybatis Mapper的xml文件中resultType值的使用说明

    mybatis Mapper的xml文件中resultType值的使用说明

    这篇文章主要介绍了mybatis Mapper的xml文件中resultType值的使用说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • java中堆内存与栈内存的知识点总结

    java中堆内存与栈内存的知识点总结

    在本篇文章里小编给大家整理的是关于java中堆内存与栈内存的知识点总结,有需要的朋友们可以跟着学习下。
    2019-12-12
  • Java实现JDK动态代理的原理详解

    Java实现JDK动态代理的原理详解

    这篇文章主要介绍了Java实现JDK动态代理的原理详解,Java常用的动态代理模式有JDK动态代理,也有cglib动态代理,本文重点讲解JDK的动态代理,需要的小伙伴可以参考一下的相关资料
    2022-07-07
  • SpringBoot+Shiro+LayUI权限管理系统项目源码

    SpringBoot+Shiro+LayUI权限管理系统项目源码

    本项目旨在打造一个基于RBAC架构模式的通用的、并不复杂但易用的权限管理系统,通过SpringBoot+Shiro+LayUI权限管理系统项目可以更好的帮助我们掌握springboot知识点,感兴趣的朋友一起看看吧
    2021-04-04
  • 基于springboot拦截器HandlerInterceptor的注入问题

    基于springboot拦截器HandlerInterceptor的注入问题

    这篇文章主要介绍了springboot拦截器HandlerInterceptor的注入问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • SpringTask实现定时任务方法讲解

    SpringTask实现定时任务方法讲解

    通过重写Schedu lingConfigurer方法实现对定时任务的操作,单次执行、停止、启动三个主要的基本功能,动态的从数据库中获取配置的定时任务cron信息,通过反射的方式灵活定位到具体的类与方法中
    2023-02-02
  • Java通过SSM完成水果商城批发平台流程

    Java通过SSM完成水果商城批发平台流程

    这是一个使用了java+SSM开发的网上水果商城批发平台,是一个实战小练习,具有水果商城批发该有的所有功能,感兴趣的朋友快来看看吧
    2022-06-06
  • Java利用序列化实现对象深度clone的方法

    Java利用序列化实现对象深度clone的方法

    这篇文章主要介绍了Java利用序列化实现对象深度clone的方法,实例分析了java序列化及对象克隆的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • HttpClient实现文件上传功能

    HttpClient实现文件上传功能

    这篇文章主要为大家详细介绍了利用HttpClient实现文件上传,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • log4j.properties 配置(实例讲解)

    log4j.properties 配置(实例讲解)

    下面小编就为大家带来一篇log4j.properties 配置(实例讲解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08

最新评论