一、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方法源码分析的更多相关文章

  1. TreeSet集合的add()方法源码解析(01.Integer自然排序)

    >TreeSet集合使用实例 >TreeSet集合的红黑树 存储与取出(图) >TreeSet的add()方法源码     TreeSet集合使用实例 package cn.itca ...

  2. Java split方法源码分析

    Java split方法源码分析 public String[] split(CharSequence input [, int limit]) { int index = 0; // 指针 bool ...

  3. invalidate和requestLayout方法源码分析

    invalidate方法源码分析 在之前分析View的绘制流程中,最后都有调用一个叫invalidate的方法,这个方法是啥玩意?我们来看一下View类中invalidate系列方法的源码(ViewG ...

  4. Linq分组操作之GroupBy,GroupJoin扩展方法源码分析

    Linq分组操作之GroupBy,GroupJoin扩展方法源码分析 一. GroupBy 解释: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值. 查询表达式: var ...

  5. jQuery实现DOM加载方法源码分析

    传统的判断dom加载的方法 使用 dom0级 onload事件来进行触发所有浏览器都支持在最初是很流行的写法 我们都熟悉这种写法: window.onload=function(){ ... }  但 ...

  6. 【Java】NIO中Selector的select方法源码分析

    该篇博客的有些内容和在之前介绍过了,在这里再次涉及到的就不详细说了,如果有不理解请看[Java]NIO中Channel的注册源码分析, [Java]NIO中Selector的创建源码分析 Select ...

  7. jQuery.extend()方法和jQuery.fn.extend()方法源码分析

    这两个方法用的是相同的代码,一个用于给jQuery对象或者普通对象合并属性和方法一个是针对jQuery对象的实例,对于基本用法举几个例子: html代码如下: <!doctype html> ...

  8. jQuery.clean()方法源码分析(一)

    在jQuery 1.7.1中调用jQuery.clean()方法的地方有三处,第一次就是在我之前的随笔分析jQuery.buildFramgment()方法里面的,其实还是构造函数的一部分,在处理诸如 ...

  9. ArrayList方法源码分析

    本文将从ArrayList类的存储结构.初始化.增删数据.扩容处理以及元素迭代等几个方面,分析该类常用方法的源码. 数据存储设计 该类用一个Object类型的数组存储容器的元素.对于容量为空的情况,提 ...

  10. TreeSet与TreeMap的源码分析 JDK7

    TreeSet存储原则是:不可重复,有序的. public TreeSet() { this(new TreeMap<E,Object>()); } public TreeSet(Comp ...

随机推荐

  1. 『Python底层原理』--CPython 虚拟机

    在 Python 编程的世界里,我们每天都在使用 python 命令运行程序,但你是否曾好奇这背后究竟发生了什么? 本文将初步探究 CPython(Python 中最流行的实现)的一些内部机制,为了更 ...

  2. macos修改hosts后清理dns缓存

    sudo killall -HUP mDNSResponder sudo killall mDNSResponderHelper sudo dscacheutil -flushcache

  3. Luogu P3177 树上染色 [ 蓝 ] [ 树形 dp ] [ 贡献思维 ]

    一道很好的树形 dp !!!!! 树上染色. 错误思路 定义 \(dp[u][i]\) 表示以 \(u\) 为根的子树中,把 \(i\) 个点染成黑色的最大收益. 但这样写,就在转移的时候必须枚举每一 ...

  4. 《Vue2 框架入门第一课:基础概念与环境搭建》

    前端宇宙的新钥匙 --Vue2 在前端开发的广袤宇宙中,Vue2 框架宛如一把闪耀的钥匙,为开发者们开启了一扇通往高效.灵活构建用户界面的大门.随着互联网技术的飞速发展,前端开发的复杂性与日俱增,对开 ...

  5. RFID基础——高频RFID协议、读写模块和标签

    RFID技术中的低频.高频.超高频有各自的优点和应用场景.其中,与我们个人生活息息相关的门禁卡.公交卡.身份证.图书标签主要用到的是高频RFID.这些应用也对应着高频RFID中不同的协议. 高频RFI ...

  6. IDEA中Maven项目修改JSP后通过配置Tomcat实现立即生效

    参考: IntelliJ IDEA 的 Project Structure 窗口中的 Artifacts 勾选 Include in project build IDEA中Facets和Artifac ...

  7. FreeSql学习笔记——12.执行Sql

    前言   FreeSql支持通过Sql语句配合ISelect生成最终的Sql语句,也可以执行原生自定义Sql语句,使操作更灵活:通过sql语句与Iselect配合使用更好控制sql语句: 简单查询 _ ...

  8. Vulnhun靶机-kioptix level 4-sql注入万能密码拿到权限ssh连接利用mysql-udf漏洞提权

    一.环境搭建 然后选择靶机所在文件夹 信息收集 本靶机ip和攻击机ip 攻击机:192.168.108.130 靶机:192.168.108.141 扫描ip 靶机ip为:192.168.108.14 ...

  9. DataX - [02] 安装部署

    操作系统:Alibaba Cloud Linux release 3 (Soaring Falcon) Java:1.8.0_372 Python:3.6.8 => 2.7.1 一.安装部署 ( ...

  10. mysql扫描全表更新状态部分失败

    1. mysql排序问题 一直以为mysql是按照主键排序的,实则排序和主键没有关系(不使用 order by 子句). 然后从 stackoverflow 上查了一下,找到了以下的回答: 没有默认的 ...