当前位置: 首页 > news >正文

java源码阅读 - TreeSet

往期文章

  • 用最简单的话讲最明白的红黑树
  • java源码阅读 - HashMap
  • 数据结构 - 堆与堆排序

文章目录

  • 往期文章
  • 一、介绍
  • 二、类的声明
  • 三、成员变量
  • 四、构造函数
  • 五、常用方法
    • 1. NavigableSet接口的实现
    • 2. SortedSet接口的实现
  • 六、总结

一、介绍

在上期文章中,我们从源码层面详细分析了java集合框架中Set一族的实现HashSet,它的内部维护了一个HashMap对象作为内部存储,也就是说HashSet的底层结构为哈希表,今天我们介绍Set的另一个实现——TreeSet,对标HashSet与HashMap的关系,我们猜想TreeSet可能会维护一个TreeMap作为内部存储,事实也确实如此,因此,TreeSet的特性均继承于TreeMap,如元素有序等。在学习TreeSet源码之前,必须对TreeMap的源码了如指掌。由于TreeMap底层实现为较复杂的红黑树,对TreeMap源码不了解的同学请一定要参考前面的文章TreeMap源码。下面我们先看一下TreeSet的UML图。

在这里插入图片描述

二、类的声明

public class TreeSet<E> extends AbstractSet<E>implements NavigableSet<E>, Cloneable, java.io.Serializable

从类的声明和上面的UML类图中可以了解到:

  • 继承AbstractSet抽象类,对其进行了扩展。
  • 实现了NavigableSet接口,表示它是一个提供导航功能的Set集合,满足Set集合的定义
  • 实现了Cloneable接口,提供了对象克隆方法,但请注意,是浅克隆
  • 实现了Serializable接口,支持序列化

三、成员变量

// HashSet的底层使用NavigableMap对象作为存储结构,
// 目前我们常用的NavigableMap实现为TreeMap
// 而TreeMap已经实现了红黑树,因此TreeSet无需再次对红黑树进行实现,直接通过TreeMap对红黑树进行数据的存取即可。
private transient NavigableMap<E,Object> m;// 虽然TreeSet使用TreeMap来操作红黑树,
// 但是TreeMap存储的是<key,value>键值对,
// 因此TreeSet在保存数据时,key为实际保存的数据,使用一个固定的对象PRESENT作为假的value值
private static final Object PRESENT = new Object();

四、构造函数

TreeSet提供了四个构造函数,由于TreeSet的底层为TreeMap,因此在TreeSet的构造方法中,都是先实例化一个TreeMap对象。

在TreeSet的众多构造函数中,有一个比较特殊的构造函数

TreeSet(NavigableMap<E,Object> m) {this.m = m;
}

该构造函数的访问修饰符为默认,因此只能被类内部和同包内的子类调用。通过接收一个NavigableMap对象,并将其作为内部的NavigableMap对象维护,比如TreeMap。

  • 无参构造

    通过TreeMap的无参构造,实例化一个TreeMap对象,作为TreeSet的内部成员变量。

    public TreeSet() {this(new TreeMap<E,Object>());
    }
    
  • 指定比较器Comparator

    其实还是调用TreeMap的构造方法public TreeMap(Comparator<? super K> comparator)来实例化一个TreeMap对象,作为TreeSet的内部成员变量。

    public TreeSet(Comparator<? super E> comparator) {this(new TreeMap<>(comparator));
    }
    
  • 通过传入一个集合构造

    先通过无参构造,实例化TreeSet对象,然后将集合中的元素通过addAll()方法批量保存到TreeSet对象中。

    其中addAll()方法的实现与TreeMap中putAll()方法的实现几乎完全相同,故不再赘述,可查看前面的文章TreeMap

    public TreeSet(Collection<? extends E> c) {this();addAll(c);
    }public  boolean addAll(Collection<? extends E> c) {// Use linear-time version if applicableif (m.size()==0 && c.size() > 0 &&c instanceof SortedSet &&m instanceof TreeMap) {SortedSet<? extends E> set = (SortedSet<? extends E>) c;TreeMap<E,Object> map = (TreeMap<E, Object>) m;Comparator<?> cc = set.comparator();Comparator<? super E> mc = map.comparator();if (cc==mc || (cc != null && cc.equals(mc))) {map.addAllForTreeSet(set, PRESENT);return true;}}return super.addAll(c);
    }
    
  • 通过传入一个有序集合构造

    在有序集合SortedSet中,提供给我们一个方法comparator()来获取有序集合中的比较器,再根据这个比较器来实例化一个TreeSet对象。如果有序集合中不存在比较器Comparator,则从TreeMap中我们也知道,键值对中的key必须实现Compareable接口中的compareTo()方法。

    其中addAll()方法的实现与TreeMap中putAll()方法的实现几乎完全相同,故不再赘述,可查看前面的文章TreeMap。

    public TreeSet(SortedSet<E> s) {this(s.comparator());addAll(s);
    }
    

五、常用方法

由于TreeSet实现NavigableSet接口,NavigableSet接口又继承于SortedSet接口。而TreeMap实现NavigableMap接口,NavigableMap接口又继承于SortedMap接口,如下图所示:

在这里插入图片描述

二者相似度极高,因此我们可以断定

  • SortedSet接口的方法都是通过调用TreeMap中实现SortedMap接口方法而实现的。

  • NavigableSet接口的方法都是通过调用TreeMap中实现NavigableMap接口方法而实现的。

下面我们通过源码进行分析:

1. NavigableSet接口的实现

  • lower()

    获取比指定元素小的元素中最大的一个元素。调用内部TreeMap对象实现NavigableMap接口的lowerKey()方法,

    public E lower(E e) {return m.lowerKey(e);
    }
    
  • floor()

    获取小于等于指定元素的元素中最大的一个元素。调用内部TreeMap对象实现NavigableMap接口的floorKey()方法,

    public E floor(E e) {return m.floorKey(e);
    }
    
  • ceiling()

    获取大于等于指定元素的元素中最小的一个元素。调用内部TreeMap对象实现NavigableMap接口的ceilingKey()方法,

    public E ceiling(E e) {return m.ceilingKey(e);
    }
    
  • higher()

    获取比指定元素大的元素中最小的一个元素。调用内部TreeMap对象实现NavigableMap接口的higherKey()方法,

    public E higher(E e) {return m.higherKey(e);
    }
    
  • pollFirst()

    获取set集合中第一个元素,并将其删除。调用内部TreeMap对象实现NavigableMap接口的pollFirstEntry()方法,获取首个键值对节点并删除后,返回该键值对节点中的key。

    public E pollFirst() {Map.Entry<E,?> e = m.pollFirstEntry();return (e == null) ? null : e.getKey();
    }
    
  • pollLast()

    获取set集合中最后一个元素,并将其删除。调用内部TreeMap对象实现NavigableMap接口的pollLastEntry()方法,获取最后一个键值对节点并删除后,返回该键值对节点中的key。

    public E pollLast() {Map.Entry<E,?> e = m.pollLastEntry();return (e == null) ? null : e.getKey();
    }
    

2. SortedSet接口的实现

  • comparator()

    获取当前实例中的比较器

    public Comparator<? super E> comparator() {return m.comparator();
    }
    
  • first()

    获取set集合中第一个元素。调用内部TreeMap对象实现SortedMap接口的firstKey()方法,获取首个键值对节点中的key。

    public E first() {return m.firstKey();
    }
    
  • last()

    获取set集合中最后一个元素。调用内部TreeMap对象实现SortedMap接口的lastKey()方法,获取最后一个键值对节点中的key。

    public E last() {return m.lastKey();
    }
    

六、总结

  • 元素有序,基于比较器或Compareable接口的compareTo()方法实现元素的排序
  • 线程不安全
  • TreeSet的底层实现为TreeMap,TreeMap的底层实现为红黑树,因此TreeSet的底层实现为红黑树,TreeSet通过调用TreeMap的方法对红黑树进行操作。


纸上得来终觉浅,绝知此事要躬行。

————————————————我是万万岁,我们下期再见————————————————

相关文章:

java源码阅读 - TreeSet

往期文章 用最简单的话讲最明白的红黑树java源码阅读 - HashMap数据结构 - 堆与堆排序 文章目录往期文章一、介绍二、类的声明三、成员变量四、构造函数五、常用方法1. NavigableSet接口的实现2. SortedSet接口的实现六、总结一、介绍 在上期文章中&#xff0c;我们从源码层面…...

写毕业论文经验贴

首先说一句不要靠近word&#xff0c;会变得不幸。最好用latex写&#xff0c;不过我当时懒得下载latex了&#xff0c;于是后期改格式花了点时间 写论文之前 事先把所有的论文都查好并且整理好&#xff0c;论文第一、二章写起来就会很快&#xff1b; 把实验做顺溜&#xff0c;实…...

2.7 进程退出、孤儿进程、僵尸进程+2.8 wait函数+2.9 waitpid函数

1.进程退出 子进程退出时&#xff1a;父进程帮助子进程回收内核区的资源 exit.c /*#include <stdlib.h>void exit(int status);#include <unistd.h>void _exit(int status);status参数&#xff1a;是进程退出时的一个状态信息。父进程回收子进程资源的时候可以获取…...

【新2023Q2模拟题JAVA】华为OD机试 - 预订酒店

最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已参加机试人员的实战技巧本篇题解:预订酒店 题目 放暑假了,橡…...

一个完整的渗透学习路线是怎样的?如何成为安全渗透工程师?

前言 1/我是如何学习黑客和渗透&#xff1f; 我是如何学习黑客和渗透测试的&#xff0c;在这里&#xff0c;我就把我的学习路线写一下&#xff0c;让新手和小白们不再迷茫&#xff0c;少走弯路&#xff0c;拒绝时间上的浪费&#xff01; 2/学习常见渗透工具的使用 注意&…...

刷完这60个标准库模块,成为Python骨灰级玩家

python强大&#xff0c;主要是因为包多&#xff0c;且不说第三方包&#xff0c;单是标准库就已让人望而生畏。 如果从第一篇整理标准库的博客算起&#xff0c;如今已有三个年头。在整理标准库的过程中&#xff0c;查阅了大量资料和官方文档&#xff0c;很多中文资料都有一个共…...

EasyExcel的简单使用(easyExcel和poi)

EasyExcel的简单使用 前言 Excel读 1.实体类 2.读监听器与测试类 3.输出结果 Excel写 1.实体类 2.写入Excel的测试类 3.输出结果 填充Excel 1.Excel模板 2.测试类 3.输出结果 前言 EasyExcel类是一套基于Java的开源Excel解析工具类&#xff0c;相较于传统的框架如Apache poi、…...

命名空间 namespace

一、命名空间的定义 定义命名空间&#xff0c;使用namespace关键字&#xff0c;后面跟命名空间的名字&#xff0c;然后接一对花括号{ } 即可&#xff0c;{ }中即为命名空间的成员。 1.一般定义 namespace test {int a 10;int b 100;int ADD(int x, int y){return x y;} }…...

我能“C”——初阶指针(上)

目录 1.什么是指针&#xff1f; 2. 指针和指针类型 3.野指针 3.1野指针的成因 3.2 如何规避野指针 1.什么是指针&#xff1f; 指针理解的2个要点&#xff1a; 1. 指针是内存中一个最小单元的编号&#xff0c;也就是地址 2. 平时口语中说的指针&#xff0c;通常指的是指针…...

Android高级工程师工资为何让人艳羡不已

很多人都想有一个月入过万的梦想&#xff0c;为了实现这个梦想&#xff0c;很多人都付出了一定的努力&#xff0c;但除了付出&#xff0c;选择一个好的行业的也是非常重要的&#xff0c;就眼下而言&#xff0c;最为多金的职业莫过于Android高级工程师&#xff0c;为什么Android…...

什么猫猫最受欢迎?Python采集猫咪交易数据

前言 在日常生活中&#xff0c;我们看到可爱的猫咪表情包&#xff0c;总是会忍不住收藏 认识的一些朋友也养了猫&#xff0c;比如橘猫、英短、加菲猫之类的 看他们发朋友圈撸猫&#xff0c;老羡慕了&#xff0c;猫咪真的太可爱啦。 你是不是也动过养猫猫的小心思呢~反正我是动…...

使用Nextcloud搭建私人云盘,并内网穿透实现公网远程访问

文章目录摘要视频教程1. 环境搭建2. 测试局域网访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问4 配置固定http公网地址4.1 保留一个二级子域名4.1 配置固定二级子域名4.3 测试访问公网固定二级子域名摘要 Nextcloud,它是ownCloud的一个分支,是一个文件…...

行业盛会|2023中国(东莞)国际测量控制及仪器仪表展览会

时间&#xff1a;2023年11月16-18日 地点&#xff1a;广东现代国际展览中心 ◆展会背景background&#xff1a; 众所周知,当今世界已经进入信息时代&#xff0c;信息技术成为推动科学技术高速发展的关键技术。…...

redis集群 服务器重启测试

redis集群 服务器重启测试1、集群规划&#xff1a;2台服务器 每台服务器运行3个redis实例2、重启2台服务器后redis实例没有自动重启最后一对主从节点比较 重启实例后和之前的主从分配3、再次重启2台服务器4、主从同步测试1、集群规划&#xff1a;2台服务器 每台服务器运行3个re…...

Diffusion的unet中用到的AttentionBlock详解

AttentionBlocktorch.splittorch中的permute的用法torch.transpose()view()torch.bmmsoftmax(x, dim-1)Diffusion的unet中用到的AttentionBlock详解class AttentionBlock(nn.Module):__doc__ r"""Applies QKV self-attention with a residual connection.Input…...

ElasticSearch索引文档写入和近实时搜索

一、基本概念 1.Segments In Lucene 众所周知&#xff0c;ElasticSearch存储的基本单元Shard&#xff0c;ES中一个Index可能分为多个Shard&#xff0c;事实上每个Shard都是一个Lucence的Index&#xff0c;并且每个Lucene Index由多个Segment组成&#xff0c;每个Segment事实上…...

【C语言蓝桥杯每日一题】——等差数列

【C语言蓝桥杯每日一题】——等差数列&#x1f60e;前言&#x1f64c;等差数列&#x1f64c;解题思路分析&#xff1a;&#x1f60d;解题源代码分享&#xff1a;&#x1f60d;总结撒花&#x1f49e;&#x1f60e;博客昵称&#xff1a;博客小梦 &#x1f60a;最喜欢的座右铭&…...

EM7电磁铁的技术参数

电磁铁可以通过更换电磁铁极头在一定范围内改善磁场的大小和磁场的均匀度 &#xff0c;并且可以通过调整极头间距改变磁场的大小。主要用于磁滞现象研究、磁化系数测量、霍尔效应研究、磁光实验、磁场退火、核磁共振、电子顺磁共振、生物学研究、磁性测量、磁性材料取向、磁性产…...

选择很重要,骑友,怎么挑选骑行装备?

骑行装备的重要性&#xff0c;已经不用多说了&#xff0c;大家也都知道。但是如何挑选&#xff0c;如何选择适合自己的骑行装备呢&#xff1f;今天我来和大家聊一聊这个问题。首先我们需要了解一个概念&#xff1a;骑行装备分为两大类&#xff1a;骑行服和骑行鞋。对于公路车来…...

【JUC面试题】Java并发编程面试题

Java并发编程 基础知识 1. 为什么要使用并发编程&#xff1f; 提升多核系统的CPU利用率一般来说一台主机上的会有多个CPU核心&#xff0c;我们可以创建多个线程&#xff0c;理论 上讲操作系统可以将多个线程分配给不同的CPU去执行&#xff0c;每个CPU执行一个线程&#xff0c…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…...