TreeSet的add方法源码分析
一、JDK 1.8 中 TreeSet 的 add 方法源码详细分析
TreeSet 是 Java 集合框架中的一个有序集合类,基于红黑树(TreeMap)实现。TreeSet 的 add 方法用于向集合中添加元素。如果元素已存在,则不会添加并返回 false;如果元素不存在,则添加并返回 true。下面我们将从 TreeSet 的 add 方法入手,逐步分析其源码实现
二、TreeSet 的 add 方法
TreeSet 的 add 方法源码如下:

参数说明
e:要添加的元素。
PRESENT:一个固定的 Object 对象,作为 TreeMap 的值(value)
返回值
如果元素 e 不存在,map.put(e, PRESENT) 返回 null,表示添加成功
如果元素 e 已存在,map.put(e, PRESENT) 返回 PRESENT,表示添加失败
三、TreeSet 的内部实现
TreeSet 的内部是基于 TreeMap 实现的。TreeSet 的元素作为 TreeMap 的键(key),而值(value)是一个固定的 PRESENT 对象(private static final Object PRESENT = new Object())
TreeSet 的构造函数
TreeSet 的构造函数会初始化内部的 TreeMap。例如:

PRESENT 对象
PRESENT 是一个静态常量,用于作为 TreeMap 的值:

四、TreeMap 的 put 方法
TreeSet 的 add 方法依赖于 TreeMap 的 put 方法。以下是 TreeMap 的 put 方法的源码(JDK 1.8):
public V put(K key, V value) {
Entry<K,V> t = root; // 获取根节点
if (t == null) { // 如果树为空
compare(key, key); // 检查键是否为 null
root = new Entry<>(key, value, null); // 创建根节点
size = 1; // 大小设置为 1
modCount++; // 修改计数器加 1
return null; // 返回 null,表示添加成功
}
int cmp;
Entry<K,V> parent;
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) // 如果键为 null
throw new NullPointerException(); // 抛出异常
Comparable<? super K> k = (Comparable<? super K>) key; // 强制转换为 Comparable
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); // 创建新节点
if (cmp < 0) // 如果键小于父节点
parent.left = e; // 将新节点作为左子节点
else // 如果键大于父节点
parent.right = e; // 将新节点作为右子节点
fixAfterInsertion(e); // 修复红黑树的性质
size++; // 大小加 1
modCount++; // 修改计数器加 1
return null; // 返回 null,表示添加成功
}
五、源码解析
1、检查树是否为空:
- 如果树为空,创建根节点并返回 null
2、比较键:
如果使用自定义比较器,调用 compare 方法比较键
如果使用自然顺序,调用 compareTo 方法比较键
3、查找插入位置:
根据比较结果,移动到左子树或右子树
如果找到相同的键,更新值并返回旧值
4、插入新节点:
- 创建新节点,并根据比较结果将其作为左子节点或右子节点
5、修复红黑树的性质:
- 调用 fixAfterInsertion 方法修复红黑树的性质(如颜色调整和旋转)
6、更新大小和修改计数器:
大小加 1
修改计数器加 1
六、总结
TreeSet 的 add 方法通过调用内部 TreeMap 的 put 方法实现元素的添加。它的核心逻辑是:
如果元素不存在,添加到 TreeMap 中并返回 true
如果元素已存在,返回 false
在 JDK 1.8 中,TreeMap 的实现基于红黑树,保证插入、删除和查找操作的时间复杂度为 O(log n)。TreeSet 的 add 方法适合需要有序集合的场景。在使用时,注意实现 Comparable 接口或提供 Comparator,并根据需求选择合适的集合类
TreeSet的add方法源码分析的更多相关文章
- TreeSet集合的add()方法源码解析(01.Integer自然排序)
>TreeSet集合使用实例 >TreeSet集合的红黑树 存储与取出(图) >TreeSet的add()方法源码 TreeSet集合使用实例 package cn.itca ...
- Java split方法源码分析
Java split方法源码分析 public String[] split(CharSequence input [, int limit]) { int index = 0; // 指针 bool ...
- invalidate和requestLayout方法源码分析
invalidate方法源码分析 在之前分析View的绘制流程中,最后都有调用一个叫invalidate的方法,这个方法是啥玩意?我们来看一下View类中invalidate系列方法的源码(ViewG ...
- Linq分组操作之GroupBy,GroupJoin扩展方法源码分析
Linq分组操作之GroupBy,GroupJoin扩展方法源码分析 一. GroupBy 解释: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值. 查询表达式: var ...
- jQuery实现DOM加载方法源码分析
传统的判断dom加载的方法 使用 dom0级 onload事件来进行触发所有浏览器都支持在最初是很流行的写法 我们都熟悉这种写法: window.onload=function(){ ... } 但 ...
- 【Java】NIO中Selector的select方法源码分析
该篇博客的有些内容和在之前介绍过了,在这里再次涉及到的就不详细说了,如果有不理解请看[Java]NIO中Channel的注册源码分析, [Java]NIO中Selector的创建源码分析 Select ...
- jQuery.extend()方法和jQuery.fn.extend()方法源码分析
这两个方法用的是相同的代码,一个用于给jQuery对象或者普通对象合并属性和方法一个是针对jQuery对象的实例,对于基本用法举几个例子: html代码如下: <!doctype html> ...
- jQuery.clean()方法源码分析(一)
在jQuery 1.7.1中调用jQuery.clean()方法的地方有三处,第一次就是在我之前的随笔分析jQuery.buildFramgment()方法里面的,其实还是构造函数的一部分,在处理诸如 ...
- ArrayList方法源码分析
本文将从ArrayList类的存储结构.初始化.增删数据.扩容处理以及元素迭代等几个方面,分析该类常用方法的源码. 数据存储设计 该类用一个Object类型的数组存储容器的元素.对于容量为空的情况,提 ...
- TreeSet与TreeMap的源码分析 JDK7
TreeSet存储原则是:不可重复,有序的. public TreeSet() { this(new TreeMap<E,Object>()); } public TreeSet(Comp ...
随机推荐
- C#/.NET/.NET Core技术前沿周刊 | 第 21 期(2025年1.6-1.12)
前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录.追踪C#/.NET/.NET Core领域.生态的每周最新.最实用.最有价值的技术文章.社区动态.优质项目和学习资源等. ...
- 聊一聊 操作系统蓝屏 c0000102 的故障分析
一:背景 1. 讲故事 今年以来不知道为啥总有些朋友加我微信,让我帮忙分析下操作系统蓝屏问题,我也觉得挺好奇的,就问了其中一位朋友,说是B站来的,我就在拼命回忆,为啥会找我分析蓝屏?突然想到了去年好像 ...
- linux:权限管理
权限概述 linux一般讲文件可存 / 取 访问的身份分为3个类别:owner.group.others,且3种身份各有 read.write.execute等权限 权限介绍 在多用户计算机系统中,权 ...
- flow pg walkthrough Intermediate
nmap nmap -p- -A -T4 -sS 192.168.114.104 Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-07 03 ...
- cxGrid列的OnValidate事件处理程序
procedure TForm1.cxGrid1DBTableView1AColumnPropertiesValidate(Sender: TObject; var DisplayValue: Var ...
- shell 条件语句基础练习
#输出1到15数字 #!/bin/bash for i in `seq 1 15` do echo -e "\033[32m$i\033[0m" done #计算1到100数字之和 ...
- Luogu P11230 CSP-J 2024 接龙 题解 [ 线性 dp ] [ 前缀和 ]
接龙:一个前缀和优化 dp 或者单调队列优化 dp 的题目. 怎么周围的人都秒了 T3 不会 T4 啊,只有我觉得 T4 很套路,T3 比较难写吗. 暴力 dp 为了避免多维的状态定义,我们把每个人的 ...
- 【忍者算法】从生活场景到回文链表:探索对称性检测|LeetCode 234 回文链表
从生活场景到回文链表:探索对称性检测 生活中的回文现象 在日常生活中,回文无处不在.比如"上海自来水来自海上"."12321"这样正着读和倒着读都一样的字符串或 ...
- MYSQL数据空洞解析
## 背景引入 MYSQL中数据表A,在删除了一半的数据后,发现表空间的大小并没有减少,这是什么原因导致的呢? 定义 当对一定量数据执行delete操作时,MySQL将数据删除后进而导致页合并或者页删 ...
- 创建Graphics对象的三种方法
参考链接:https://www.cnblogs.com/wax01/p/4982691.html 方法一.利用控件或窗体的Paint事件中的PainEventArgs 在窗体或控件的Paint事件中 ...