概述

文章的内容基于JDK1.7进行分析,之所以选用这个版本,是因为1.8的有些类做了改动,增加了阅读的难度,虽然是1.7,但是对于1.8做了重大改动的内容,文章也会进行说明。

TreeSet实现了SortedSet接口,它是一个有序的集合类,TreeSet的底层是通过TreeMap实现的。TreeSet并不是根据插入的顺序来排序,而是根据实际的值的大小来排序。TreeSet也支持两种排序方式:

自然排序

自定义排序

数据结构

继承关系

java.lang.Object

java.util.AbstractCollection

java.util.AbstractSet

java.util.TreeSet

实现接口

Serializable, Cloneable, Iterable, Collection, NavigableSet, Set, SortedSet

基本属性

private transient NavigableMap m; //存放元素的集合

private static final Object PRESENT = new Object(); //m中key 对应的value

重要方法深度解析

构造方法

//相同包下可以访问的构造方法,将指定的m赋值为m

TreeSet(NavigableMap m) {

this.m = m;

}

//无参构造方法,创建一个空的TreeMap对象,并调用上面的构造方法

public TreeSet() {

this(new TreeMap());

}

//指定比较器,并用指定的比较器创建TreeMap对象

public TreeSet(Comparator super E> comparator) {

this(new TreeMap<>(comparator));

}

//将指定的集合C转化为TreeSet

public TreeSet(Collection extends E> c) {

this();

addAll(c);

}

//将SortedMap中的元素转化为TreeMap对象

public TreeSet(SortedSet s) {

this(s.comparator());

addAll(s);

}

通过上面的构造方法,可以看出TreeSet的底层是用TreeMap实现的。在构造方法中会创建一个TreeMap实例,用于存放元素,另外TreeSet是有序的,也提供了制定比较器的构造函数,如果没有提供比较器,则采用key的自然顺序进行比较大小,如果指定的比较器,则采用指定的比较器,进行key值大小的比较。

add()方法和remove()方法都比较的简单都是调用TreeMap的方法进行实现。此处不在单独列出

源码解析

public class TreeSet extends AbstractSet

implements NavigableSet, Cloneable, java.io.Serializable

{

//存放元素的map对象

private transient NavigableMap m;

//key-value ,不同的键都会对象相同的value, value = PRESENT

private static final Object PRESENT = new Object();

//指定的map对象

TreeSet(NavigableMap m) {

this.m = m;

}

//无参构造方法,初始化一个TreeMap对象

public TreeSet() {

this(new TreeMap());

}

//构造方法,指定比较器

public TreeSet(Comparator super E> comparator) {

this(new TreeMap<>(comparator));

}

//将集合中的元素转化为TreeSet存储

public TreeSet(Collection extends E> c) {

this();

addAll(c);

}

//构造方法,SortedSet转化为TreeSet存储,并使用SortedSet的比较器

public TreeSet(SortedSet s) {

this(s.comparator());

addAll(s);

}

//遍历方法,返回m.keyset集合

public Iterator iterator() {

return m.navigableKeySet().iterator();

}

//逆序排序的迭代器

public Iterator descendingIterator() {

return m.descendingKeySet().iterator();

}

/**

* @since 1.6

*/

public NavigableSet descendingSet() {

return new TreeSet<>(m.descendingMap());

}

//返回 m 包含的键值对的数量

public int size() {

return m.size();

}

//是否为空

public boolean isEmpty() {

return m.isEmpty();

}

//是否包含指定的key

public boolean contains(Object o) {

return m.containsKey(o);

}

//添加元素,调用m.put方法实现

public boolean add(E e) {

return m.put(e, PRESENT)==null;

}

//删除方法,调用m.remove()方法实现

public boolean remove(Object o) {

return m.remove(o)==PRESENT;

}

//清除集合

public void clear() {

m.clear();

}

//将一个集合中的所有元素添加到TreeSet中

public boolean addAll(Collection extends E> c) {

// Use linear-time version if applicable

if (m.size()==0 && c.size() > 0 &&

c instanceof SortedSet &&

m instanceof TreeMap) {

SortedSet extends E> set = (SortedSet extends E>) c;

TreeMap map = (TreeMap) m;

Comparator super E> cc = (Comparator super E>) 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);

}

//返回子集合,通过 m.subMap()方法实现

public NavigableSet subSet(E fromElement, boolean fromInclusive,

E toElement, boolean toInclusive) {

return new TreeSet<>(m.subMap(fromElement, fromInclusive,

toElement, toInclusive));

}

//返回set的头部

public NavigableSet headSet(E toElement, boolean inclusive) {

return new TreeSet<>(m.headMap(toElement, inclusive));

}

//返回尾部

public NavigableSet tailSet(E fromElement, boolean inclusive) {

return new TreeSet<>(m.tailMap(fromElement, inclusive));

}

//返回子Set

public SortedSet subSet(E fromElement, E toElement) {

return subSet(fromElement, true, toElement, false);

}

//返回set的头部

public SortedSet headSet(E toElement) {

return headSet(toElement, false);

}

//返回set的尾部

public SortedSet tailSet(E fromElement) {

return tailSet(fromElement, true);

}

//返回m使用的比较器

public Comparator super E> comparator() {

return m.comparator();

}

//返回第一个元素

public E first() {

return m.firstKey();

}

//返回最后一个元素

public E last() {

return m.lastKey();

}

//返回set中小于e的最大的元素

public E lower(E e) {

return m.lowerKey(e);

}

//返回set中小于/等于e的最大元素

public E floor(E e) {

return m.floorKey(e);

}

//返回set中大于/等于e的最大元素

public E ceiling(E e) {

return m.ceilingKey(e);

}

//返回set中大于e的最小元素

public E higher(E e) {

return m.higherKey(e);

}

//获取TreeSet中第一个元素,并从Set中删除该元素

public E pollFirst() {

Map.Entry e = m.pollFirstEntry();

return (e == null) ? null : e.getKey();

}

//获取TreeSet中最后一个元素,并从Set中删除该元素

public E pollLast() {

Map.Entry e = m.pollLastEntry();

return (e == null) ? null : e.getKey();

}

//克隆方法

public Object clone() {

TreeSet clone = null;

try {

clone = (TreeSet) super.clone();

} catch (CloneNotSupportedException e) {

throw new InternalError();

}

clone.m = new TreeMap<>(m);

return clone;

}

//将对象写入到输出流中。

private void writeObject(java.io.ObjectOutputStream s)

throws java.io.IOException {

// Write out any hidden stuff

s.defaultWriteObject();

// Write out Comparator

s.writeObject(m.comparator());

// Write out size

s.writeInt(m.size());

// Write out all elements in the proper order.

for (E e : m.keySet())

s.writeObject(e);

}

//从输入流中读取对象的信息

private void readObject(java.io.ObjectInputStream s)

throws java.io.IOException, ClassNotFoundException {

// Read in any hidden stuff

s.defaultReadObject();

// Read in Comparator

Comparator super E> c = (Comparator super E>) s.readObject();

// Create backing TreeMap

TreeMap tm;

if (c==null)

tm = new TreeMap<>();

else

tm = new TreeMap<>(c);

m = tm;

// Read in size

int size = s.readInt();

tm.readTreeSet(size, s, PRESENT);

}

//序列化版本号

private static final long serialVersionUID = -2479143000061671589L;

}

总结

TreeSet是一个有序的集合,基于TreeMap实现,支持两种排序方式:自然排序和定制排序。

TreeSet是非同步的,线程不安全的。

少年听雨歌楼上,红烛昏罗帐。

壮年听雨客舟中,江阔云低,断雁叫西风。

感谢支持!

---起个名忒难

java treeset原理_Java集合 --- TreeSet底层实现和原理(源码解析)相关推荐

  1. 【详解】Ribbon 负载均衡服务调用原理及默认轮询负载均衡算法源码解析、手写

    Ribbon 负载均衡服务调用 一.什么是 Ribbon 二.LB负载均衡(Load Balancer)是什么 1.Ribbon 本地负载均衡客户端 VS Nginx 服务端负载均衡的区别 2.LB负 ...

  2. Flink 全网最全资源(视频、博客、PPT、入门、原理、实战、性能调优、源码解析、问答等持续更新)

    Flink 学习 https://github.com/zhisheng17/flink-learning 麻烦路过的各位亲给这个项目点个 star,太不易了,写了这么多,算是对我坚持下来的一种鼓励吧 ...

  3. Java熔断框架有哪些_降级熔断框架 Hystrix 源码解析:滑动窗口统计

    降级熔断框架 Hystrix 源码解析:滑动窗口统计 概述 Hystrix 是一个开源的降级熔断框架,用于提高服务可靠性,适用于依赖大量外部服务的业务系统.什么是降级熔断呢? 降级 业务降级,是指牺牲 ...

  4. java list原理_Java集合:ArrayList的实现原理

    目录: 一. ArrayList概述: ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单 ...

  5. java迭代器创建后mutx锁,java集合【5】—— Collections接口源码解析

    一.Collections接口是做什么的? 用官网文档的介绍:The polymorphic algorithms described here are pieces of reusable func ...

  6. collection集合 多少钱_Java 集合(2)-- Iterator接口源码超级详细解析

    一.iterator接口介绍 iterator接口,也是集合大家庭中的一员.和其他的Map和Collection接口不同,iterator 主要是为了方便遍历集合中的所有元素,用于迭代访问集合中的元素 ...

  7. java executor 源码_Java线程池ThreadPoolExecutor深度探索及源码解析

    我们的程序里,时常要使用多线程.因此多线程的管理变的尤为重要.ThreadPoolExecutor很好的解决了这一点.本篇文章主要从源码入手,分析ThreadPoolExecutor的原理. 1.标记 ...

  8. java天眼培训_Java天眼大型分布式跟踪系统 附带源码_IT教程网

    资源名称:Java天眼大型分布式跟踪系统 附带源码 教程内容: APP: 接入skyeye-client的系统会通过kafkaAppender向kafka写入日志 es-indexer-group: ...

  9. java幻灯片效果_Java实现多种幻灯片切换特效(附源码)

    Java实现多种幻灯片切换特效(附源码)以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 功能说明 代码实现了多种幻灯片变 ...

最新文章

  1. Postman系列之@RequestBody修饰的对象传参数
  2. 数学与当代生命科学(吴家睿)
  3. 遍历当前目录下的所有子目录例子(自动生成SQl语句工具)
  4. float 精度_float相加产生精度损失的原因是什么?
  5. 持续集成实验个人总结
  6. ensp保存文件在哪_eNSP——配置通过FTP进行文件操作
  7. iOS应用开发的五个Java开源工具
  8. 软件测试nodejs面试题,nodejs单元测试和性能测试
  9. 按英语体育计算机创建透视表,数据透视表和数据透视图概述
  10. ORACLE ebs 11.5.10 for linux 安装心得
  11. iOS 编译后的Archiveing 界面在 Windows-organizer 下
  12. xp本地调试php代码,Windows XP下简单配置本机PHP调试环境
  13. 四位共阳数码管与共阴数码管的c语言,4位共阳LED数码管与常用共阳极数码管型号...
  14. springboot集成Mybatis返回的值为null
  15. 火车售票-线程3种实现
  16. ppt模板页面过渡动画效果怎么制作?
  17. java 锁旗标_Java基础知识点整理(一)
  18. 小程序使用腾讯地图获取当前位置和地图选取位置
  19. PHP代码从数据库中获取数据
  20. 最近更换系统盘踩了不少坑,主要是软件运行错误,造成原成原系统盘被损毁

热门文章

  1. java 操作uart串口_【tty】应用程序调用write写串口调用流程
  2. linux 环境 下面 yum 安装nginx
  3. vue select js 设置默认值
  4. c语言实现字符串中提取数字,遇到非字符串则换行
  5. html5页面默认的字符集是什么,HTML 字符集
  6. Enrichment plot的另一种展示
  7. python中for语句用法_python中for循环的用法
  8. GitHub 的项目徽章
  9. R语言与数据分析(9)R与Excel
  10. Bio-protocol第一届生物实验短视频大赛集锦(三)——软件使用篇