Java之TreeSet和TreeMap

本文深入解析了Java集合框架中的TreeSet和TreeMap。TreeSet基于TreeMap实现,两者都实现了有序性。默认情况下,它们按照Key的自然排序进行排序,如字符串的compareTo方法。若需自定义排序,可以通过传入Comparator来实现。当使用无参构造器时,添加的元素必须实现Comparable接口。文章通过源码分析,详细阐述了TreeSet和TreeMap的添加元素过程,以及如何根据比较规则决定元素的位置。同时,指出了如果不遵循比较规则可能导致的问题和解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TreeSet和TreeMap之间的关系

TreeSet的底层是TreeMap
和HashSet和HashMap的关系一样

TreeSet

继承关系

在这里插入图片描述
Set接口的实现类
关于Set接口可以看我的Java值单列集合

基本介绍

重点和其他的区别是,可以排序(按照你想要的方式)
当我们使用无参构造器创建TreeSet时
仍然是无序的
如果你希望按照添加的元素按照字符串大小排序
需要使用TreeSet一个构造器可以传入一个比较器Compartor(接口)
使用匿名内部类在这里插入图片描述
在这里插入图片描述
但compare返回值只是一个数,要想真正了解怎么进行排序
还是要看源码

底层的排序机制

在这里插入图片描述

在这里插入图片描述
TreeSet的底层是TreeMap
把我们传入的比较器传给了TreeMap的一个属性comparator

看add方法的运行比较机制
在这里插入图片描述
这里还是TreeSet的put方法

然后到TreeMap的put方法

这里我只截取了put方法里面的比较那一部分

  Comparator<? super K> cpr = comparator;//把我们的匿名内部类传给cpr
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);//调用我们定义的方法
                if (cmp < 0)//返回值大于0,左边
                    t = t.left;
                else if (cmp > 0)//返回值小于0,放右边
                    t = t.right;
                else
                    return t.setValue(value);//等于0的换直接返回
                    //不会添加
            }

key是我们传入的对象
然后t.key是哪个比较的对象
遵循compare规则
key如果和t.key比较返回值大于0
向左放
小于0,向右放
等于0,不添加

TreeMap

基本介绍

在这里插入图片描述
默认的话是按字符串的大小排序的大的放前面
就是String的compareTo机制

如果你想按照字符串长度比较
可以这样设计
在这里插入图片描述
这里是Entry存放K-V
如果你放两个字符串铲毒相同就放不进去了

源码

源码分析和前面的TreeSet相同

Collections工具类

在这里插入图片描述
都是静态方法,且直接对集合进行操作
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
min和max情况差不多不写了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

易错

TreeMap和TreeSet
使用无参构造的时候
add/put进去的key值
必须实现Compartor接口在这里插入图片描述
解决方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/fbbcb0d36810451b9925867edce63f

让Person实现Compartor接口并重写compareTo方法
注意如果返回值都是0的话只能添加一个new Person()对象
对比相同不添加

### JavaTreeSet TreeMap数据结构及使用方法 #### TreeSet 数据结构 TreeSet 是基于 NavigableSet 接口实现的一个有序集合类,其内部通过 TreeMap 来存储元素。因此,TreeSet 底层实际上依赖于红黑树来维护元素之间的顺序[^1]。 #### 创建初始化 TreeSet ```java // 导入必要的包 import java.util.TreeSet; public class Main { public static void main(String[] args) { // 初始化一个空的 TreeSet 对象,默认自然排序 TreeSet<Integer> treeSet = new TreeSet<>(); // 添加一些整数到 TreeSet 集合中 treeSet.add(5); treeSet.add(3); treeSet.add(7); System.out.println(treeSet); // 输出: [3, 5, 7] } } ``` #### TreeMap 数据结构 TreeMap 实现了 SortedMap 接口,并且同样采用红黑树作为底层数据结构。这使得它能够高效地执行增删查改操作的同时保持键值对按指定顺序排列[^2]。 #### 创建初始化 TreeMap ```java // 导入必要的包 import java.util.TreeMap; public class Main { public static void main(String[] args) { // 构造一个新的、按照默认比较器升序排列 key-value 键值对映射表 TreeMap<String, Integer> map = new TreeMap<>(); // 插入若干条记录 map.put("apple", 10); map.put("banana", 20); map.put("orange", 30); // 打印整个映射表的内容 System.out.println(map); // 输出: {apple=10, banana=20, orange=30} } } ``` #### TreeSet TreeMap 的区别 尽管两者都利用了相同的红黑树机制来进行高效的查找与遍历,但是它们之间存在显著差异: - **功能定位不同**:TreeSet 主要用于保存不重复的对象序列;而 TreeMap 则是用来关联唯一性的键与其对应的值。 - **继承层次有别**:前者实现了 Set 接口并扩展自 AbstractSet 类;后者则是 Map 接口中的一员,具体来说是从 AbstractMap 抽象基类派生而来[^3]。 - **性能特点各异**:由于 TreeMap 存储的是键值对,在访问特定项时可能需要额外的时间开销去检索相应的 value 值;相比之下,当只需要关心成员本身而不涉及任何附加信息的情况下,TreeSet 可能会更加快捷方便。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小袁拒绝摆烂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值