首页 > 编程语言 >7.TreeMap源码解析

7.TreeMap源码解析

时间:2022-10-24 22:33:53浏览次数:45  
标签:解析 TreeMap 源码 key 红黑树 Entry null 节点 cmp


1.数据结构
TreeMap的底层数据结构是红黑树,和HashMap的红黑树结构一样。不同的是,TreeMap利用红黑树左节点小,右节点大的性质,根据key进行排序,使每个元素能够插入到红黑树的适当位置,维护了key的大小关系,适用于key需要排序的场景。因为底层使用的是平衡红黑树的结构,所以containsKey、get、put、remove等方法的时间复杂度都是log(n)。
源码

public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable{
//比较器,如果外部有传进来Comparator比较器,首先用外部的
//如果外部比较器为空,则使用key实现的Comparable的compareTo方法
private final Comparator<? super K> comparator;

//红黑树的根节点
private transient Entry<K,V> root;

//红黑树中已有的元素大小
private transient int size = 0;

//树结构变化的版本号,用于迭代过程中的快速失败场景
private transient int modCount = 0;

//红黑树的节点
static final class Entry<K,V> implements Map.Entry<K,V> {}
}

2.新增
新增key和value的源码如下所示。
源码

public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable{
public V put(K key, V value) {
Entry<K,V> t = root;
//判断红黑树的节点是否为空,为空的话,新增的节点直接作为根节点
if (t == null) {
//compare方法限制了key不能为null
compare(key, key);
//成为根节点
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
//根据红黑树左小右大的特性,进行判断,找到新增节点的父节点
Comparator<? super K> cpr = comparator;
if (cpr != null) {
//自旋找到key应该新增的位置
do {
//一次循环结束时,parent就是上次比过的对象
parent = t;
//通过compare来比较key的大小
cmp = cpr.compare(key, t.key);
//key小于t,把t左边的值赋予t,因为红黑树左边的值比较小,循环再比
if (cmp < 0)
t = t.left;
//key大于t,把t右边的值赋予t,因为红黑树右边的值比较大,循环再比
else if (cmp > 0)
t = t.right;
//如果相等的话,直接覆盖原值
else
return t.setValue(value);
//t为空,说明已经到叶子节点了
} 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);
}
//在父节点的左边或右边插入新增节点
Entry<K,V> e = new Entry<>(key, value, parent);
//cmp代表最后一次对比的大小,小于0 ,代表e在上一节点的左边
if (cmp < 0)
parent.left = e;
//大于0 ,代表e在上一节点的右边,相等的情况第二步已经处理了
else
parent.right = e;
//着色旋转,直至达到平衡
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
}

源码解析

  1. 新增节点时,利用红黑树左小右大的特性,从根节点不断往下查找,直到节点的值是null为止,节点为null说明到达了叶子结点。
  2. 查找过程中,若发现key值已经存在,则直接覆盖。
  3. TreeMap是不支持key是null的。


标签:解析,TreeMap,源码,key,红黑树,Entry,null,节点,cmp
From: https://blog.51cto.com/u_15843693/5791482

相关文章

  • 5.List源码面试题集锦
    1.新建一个ArrayList,现在add一个值,此时数组的大小是多少?下一次扩容前最大可用大小是多少?答:此处数组的大小是1,下一次扩容前最大可用大小是10。因为ArrayList无参构造器初始......
  • 4.LinkedList源码解析
    1.数据结构LinkedList底层数据结构是一个双向链表,整体结构如上图所示,链表中的每个节点都可以向前或者向后追溯。源码privatestaticclassNode<E>{//节点值Eite......
  • 3.ArrayList源码解析
    1.数据结构ArrayList的数据结构是一个数组,如上图所示,图中展示的是一个长度为10的数组,从1开始计数,index表示数组的下标,从0开始计数,elementData表示数组元素。除此之外,源码中......
  • 1.String源码解析
    1.不变性这里说的不变性指的是类值一旦被初始化,就不能再被改变了,如果被修改,将会是新的类,如程序1-1所示。//程序1-1publicclassApp{publicstaticvoidmain(String[......
  • 2.Integer源码解析
    1.取值范围和基本数据类型源码publicfinalclassIntegerextendsNumberimplementsComparable<Integer>{//该值用于定义Integer取值的最小值@Nativepublicst......
  • 认识 Redis client-output-buffer-limit 参数与源码分析
    概述Redis的​​client-output-buffer-limit​​可以用来强制断开无法足够快从redis服务器端读取数据的客户端。保护机制规则如下:[hardlimit]大小限制,当某一客户端缓......
  • timedatectl解析
    一,timedatectl输出解析root@sonic:/home/admin#timedatectl             Localtime:Mon2022-10-2421:01:56CST           Universalti......
  • WebRTC源码学习02---webrtc源码编译安装(Mac)
    参考文献https://webrtc.org.cn/mirror/ (主要参考文章)https://www.an.rustfisher.com/webrtc/intro/sync-build/(参考一下代理设置)https://blog.csdn.net/dangwei_90/ar......
  • 基于ssm高校科研管理系统-计算机毕业设计源码+LW文档
    【摘要】高校科研管理是一项重要而又繁琐的工作,有效的信息管理平台可以大大缓解科研管理压力,减少工作量。本文以石河子大学信息科学与技术学院为应用背景,开发教师教学信息......
  • 基于ssm工商学院办公用品管理信息系统设计与实现-计算机毕业设计源码+LW文档
    摘 要本高校科研管理系统设计目标是实现高校科研管理的信息化管理,提高管理效率,使得高校科研管理工作规范化、科学化、高效化。本文研究的高校科研管理系统基于SSM架构,采......