当前位置: 首页 > 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…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

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

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

华为OD机试-最短木板长度-二分法(A卷,100分)

此题是一个最大化最小值的典型例题&#xff0c; 因为搜索范围是有界的&#xff0c;上界最大木板长度补充的全部木料长度&#xff0c;下界最小木板长度&#xff1b; 即left0,right10^6; 我们可以设置一个候选值x(mid)&#xff0c;将木板的长度全部都补充到x&#xff0c;如果成功…...