当前位置: 首页 > 编程日记 > 正文

TreeSet集合(自然排序和比较器排序)

TreeSet集合

自然排序和比较器排序

​ 当指执行插入排序、希尔排序、归并排序等算法时,比较两个对象“大小”的比较操作。我们很容易理解整型的 i>j 这样的比较方式,但当我们对多个对象进行排序时,如何比较两个对象的“大小”呢?这样的比较 stu1 > stu2 显然是不可能通过编译的。为了解决如何比较两个对象大小的问题,JDK提供了两个接口java.lang.Comparablejava.util.Comparator

TreeSet集合是Set集合的一个子实现类,它是基于TreeMap中的NavigableSet接口实现的
TreeSet集合是默认通过自然排序将集合中的元素进行排序
汉字的顺序根据Unicode 码表排序

TreeSet有两种排序方式:

  1. 自然排序:java.lang.Comparable

    • Comparable 接口中只提供了一个方法: compareTo(Object obj),该方法的返回值是 int 。如果返回值为正数,则表示当前对象(调用该方法的对象)比 obj 对象“大”;反之“小”;如果为零的话,则表示两对象相等。
  2. 比较器排序:java.util.Comparator

让我们先来看看一个例题:

package com.xdkj.Test09;import java.util.TreeSet;public class TreeSetDemo {public static void main(String[] args) {TreeSet<Integer> set = new TreeSet<Integer>();set.add(17);set.add(25);set.add(23);set.add(14);set.add(17);set.add(30);for (Integer s : set) {System.out.println(s);}}
}运行结果:
14
17
23
25
30

根据上述结果可以看出TreeSet集合是自然排序和去重的,为什么会达到这样的效果呢?

TreeSet集合的无参构造就是属于自然排序

TreeSet<Integer> set= new TreeSet<Integer>();

这是因为TreeSet集合依赖于TreeMap的红黑树结构实现的,下面让我们根据上述例题去看看红黑树结构的理解:

set.add(17);
set.add(25);
set.add(23);
set.add(14);
set.add(17);
set.add(30);

17先进行存储,所以将17作为根节点,与后面的元素进行比较,25进来后与17相比,比17大,所以成为17的右孩子,放在17的右边,23进来比17大所以要放在17的右边,但是和25比较比他小,所以放在25的左边,接下来1417小放在17的左边,17进来与17的值一样不理睬,继续下个30,比17大比25大,放在右边25 的右边,绘成图就是二叉图方式,结构一定是自平衡的

使用TreeSet进行自定义函数的排序,对年龄由小到大进行排序

package com.xdkj.Test09;public class Student implements Comparable<Student> {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}//因为上面Student类实现了comparable接口,所以必须重写comparaTo方法才能达到排序的效果@Overridepublic int compareTo(Student s) {// return 0;/*** 因为这是我们自定义的类,系统并没有告诉我们如何进行排序* 所以需要我们自己手动进行排序* 需求:按年龄由小到大进行排序*///年龄进行排序,由小到大int num = this.age - s.age;//当年龄大小相等时,比较名字int num2 = num == 0 ? this.name.compareTo(s.getName()) : num;return num2;}}
package com.xdkj.Test09;import java.util.TreeSet;public class StudentDemo {public static void main(String[] args) {//创建TreeSet集合对象TreeSet<Student> set = new TreeSet<Student>();//创建学生对象,这里的学生姓名不要写成汉字,因为每个汉字的字节大小不一样Student s1 = new Student("dilireba", 27);Student s2 = new Student("gaowen", 25);Student s3 = new Student("zhaoxingxing", 24);Student s4 = new Student("wuxuanyi", 23);Student s5 = new Student("dilireba", 27);set.add(s1);set.add(s2);set.add(s3);set.add(s4);set.add(s5);//增强for循环for (Student st : set) { System.out.println(st.getName() + "---" + st.getAge());}}
}运行结果:
wuxuanyi---23
zhaoxingxing---24
gaowen---25
dilireba---27

由上例可以看出我们在学生类上实线了comparable接口,并且在学生类中重写了comparaTo方法,当我们没有进行以上的这些操作时,运行时就会出现这样的错误,

Exception in thread “main” java.lang.ClassCastException: com.TreeSetDome.Student cannot be cast to java.lang.Comparable

因为没有实现comparable接口,所以会出现以上的这个异常,但是为什么在前面添加数字的时候并不需要实现comparable接口呢?这是添加数字时我们确定了类型为Integer类型,它本身就已经实现了comparable接口,不需要我们再去添加,具体可以去API中观看,所以今后在使用TreeSet创建自定义类排序的时候,一定要自己去实现comparable接口,和重写comparaTo方法

上述中我们重写的ComparaTo方法是按照年龄来排序的,接下来让我们按照姓名的长度以及年龄的大小来排序:

@Override
public int compareTo(Student s) {/*** 因为这是我们自定义的类,系统并没有告诉我们如何进行排序* 所以需要我们自己手动进行排序* 需求:按姓名的长度来排序,然后再以年龄的大小来排序*///按姓名的长短来排序,由小到大排序int num = this.getName().length() - s.getName().length();//再去比较的姓名的内容是否一致int num2 = num == 0 ? this.getName().compareTo(s.getName()) : num;//名字一致,有时候并不是同一个人 还得再去比较年龄的大小int num3 = num2 == 0 ? this.age - s.age : num2;return num3;//这是重写的comparaTo方法,我新添加了一个学生变量 Student s6=new Student("dilireba",25);}运行结果:
gaowen---25
dilireba---25
dilireba---27
wuxuanyi---23
zhaoxingxing---24

上面我们介绍了自然排序法,自然排序法主要就是运用TreeSet的无参构造,通过实现comparable接口中的comparaTo方法去进行自然排序,接下来让我们看看比较器排序,看看二者的不同

package com.xdkj.Test10;public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
package com.xdkj.Test10;import java.util.Comparator;public class ComparatorDome implements Comparator<Student> {/*** 因为测试类中TreeSet集合的引用参数是接口,所以需要创建这个 子实现类去实现这个接口* 这里的s1就相当于自然排序中的this,s2相当于s* 先按名字的长度,当长度一致时,再按年龄的大小进行排序*/public int compare(Student s1, Student s2) {//判断姓名长度的大小int num = s1.getName().length() - s2.getName().length();//长度一致时,比较内容int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;//内容一致时,比较年龄的大小int num3 = num2 == 0 ? (s1.getAge() - s2.getAge()) : num2;return num3;}
}
package com.xdkj.Test10;import java.util.TreeSet;public class StudentDome {public static void main(String[] args) {//创建TreeSet集合对象,运用比较器排序//Comparator是一个接口,所以我们得创建一个子实现类去实现它TreeSet<Student> set = new TreeSet<Student>(new ComparatorDome());//创建学生对象Student s1 = new Student("dilireba", 27);Student s2 = new Student("gaowen", 25);Student s3 = new Student("zhaoxingxing", 24);Student s4 = new Student("wuxuanyi", 23);Student s5 = new Student("dilireba", 25);Student s6 = new Student("dilireba", 25);//将学生对象添加到集合中set.add(s1);set.add(s2);set.add(s3);set.add(s4);set.add(s5);set.add(s6);//增强for循环遍历for (Student s : set) {System.out.println(s.getName() + "---" + s.getAge());}}
}运行结果:
gaowen---25
dilireba---25
dilireba---27
wuxuanyi---23
zhaoxingxing---24

除了创建子实现类去实现Comparator接口,我们还可以在测试类中通过匿名内部类的方式去测试,就不用单独去创建一个子实现类了

在这里学生类我就不写了,上面有,直接写测试类中的匿名内部类了

package com.xdkj.Test10;import java.util.Comparator;
import java.util.TreeSet;/*** @Author:Lenvo* @Description:* @Date: 2020-12-16 16:21*/
public class StudentDome {public static void main(String[] args) {//创建TreeSet集合对象,运用比较器排序//Comparator是一个接口,所以我们得创建一个子实现类去实现它//匿名内部类的使用TreeSet<Student> set = new TreeSet<Student>(new Comparator<Student>() {@Overridepublic int compare(Student s1, Student s2) {//判断姓名长度的大小int num = s1.getName().length() - s2.getName().length();//长度一致时,比较内容int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;//内容一致时,比较年龄的大小int num3 = num2 == 0 ? (s1.getAge() - s2.getAge()) : num2;return num3;}});//创建学生对象Student s1 = new Student("dilireba", 27);Student s2 = new Student("gaowen", 25);Student s3 = new Student("zhaoxingxing", 24);Student s4 = new Student("wuxuanyi", 23);Student s5 = new Student("dilireba", 25);Student s6 = new Student("dilireba", 25);//将学生对象添加到集合中set.add(s1);set.add(s2);set.add(s3);set.add(s4);set.add(s5);set.add(s6);//增强for循环遍历for (Student s : set) {System.out.println(s.getName() + "---" + s.getAge());}}
}运行结果:
gaowen---25
dilireba---25
dilireba---27
wuxuanyi---23
zhaoxingxing---24

相关文章:

java字节流

一 字节流 1.1字节输出流OutputStream OutputStream是一个抽象类&#xff0c;操作的数据都是字节。 输出流中定义都是写write方法&#xff0c;如下图: 1.1.1 FileOutputStream类 OutputStream有很多子类&#xff0c;其中子类FileOutputStream可用来写入数据到文件。FileOutput…

MySQL:讨人喜欢的 MySQL replace into 用法(insert into 的增强版)

讨人喜欢的 MySQL replace into 用法&#xff08;insert into 的增强版&#xff09; 在向表中插入数据的时候&#xff0c;经常遇到这样的情况&#xff1a;1. 首先判断数据是否存在&#xff1b; 2. 如果不存在&#xff0c;则插入&#xff1b;3.如果存在&#xff0c;则更新。 在 …

读农民工兄弟学C#文章后的感觉

呵呵,这些文章让原本枯燥的技术文章变得简单,通俗,易懂此类文章是编程入门新手必读的好文章,当然高手可以看一下这些文章的语言风格,等日后自己出书时,可以参考之!哈哈,哪天我也出一本属于自己的技术书^_^好可惜的是自己离"高手"还有那么一段路要走!当然喽,我不是高手…

36晋级12第五场:冯志刚决胜入围(节目视频)

视频地址&#xff1a;[url]http://win.cn.yahoo.com/070613/16/mn53.html[/url]比赛时间&#xff1a;2007年4月17日 选手&#xff1a;王阳、冯志刚、刘恩霞、王嵩 评委&#xff1a; 熊晓鸽&#xff1a;IDG创业投资基金 创始合伙人 马云&#xff1a;阿里巴巴集团董事局主席及雅虎…

顯示密碼安全性強度

<div class"from-nav"><div class"Mtitle"><span>密码:</span></div><div class"Mright"><input name"password"type"password"id"password"size"20"class&quo…

HashMap集合遍历的五种方式

文章目录创建HashMap集合&#xff0c;添加数据一、第一种foreach遍历二、第二种foreach遍历三、第一种迭代器遍历 效率高&#xff08;建议使用&#xff09;四、第二种迭代器遍历 效率低&#xff08;不建议使用&#xff09;五、JDK8新特性&#xff0c;通过lambda遍历Map创建Hash…

JAVA核心技术I---JAVA基础知识(查漏补缺private,static)

一&#xff1a;private对于类和对象&#xff08;同C&#xff09; private是只有这个类内部可以访问&#xff08;类的成员函数和定义初始化&#xff09; private是类之间的限制&#xff0c;而不是对对象的限制《重点》 同类对象是可以直接访问对象的私有成员 class priTest{priv…

『TensorFlow』命令行参数解析

argparse很强大&#xff0c;但是我们未必需要使用这么繁杂的东西&#xff0c;TensorFlow自己封装了一个简化版本的解析方式&#xff0c;实际上是对argparse的封装 脚本化调用tensorflow的标准范式&#xff1a; import pprint import tensorflow as tfflags tf.app.flags# 脚本…

IIS重起批处理

将以下代码保存到一个BAT文件中,执行后便可释放所有被锁定的组件。执行顺序是&#xff1a;停止&#xff37;&#xff37;&#xff37;服务&#xff0d;〉停止组件保护&#xff0d;〉开启组件保护&#xff0d;〉开启&#xff37;&#xff37;&#xff37;服务。net stop w3svc /…

RenderTree渲染树

RenderTree渲染树对类中的静态成员有很重要的关系&#xff0c;这个和多态是有很重要的关系&#xff0c;举个简单的例子&#xff0c;在游戏中&#xff0c;马里奥需要渲染&#xff0c;蘑菇也需要渲染&#xff0c;怪兽也需要渲染&#xff0c;其是串在一个树上的&#xff0c;但是不…

JAVA IO流复制文件夹及里面的所有文件

public static void main(String[] args) throws Exception {//复制到哪个路径&#xff08;path&#xff09;中String path "E:\\main";File file new File("F:\\main");copyAll(file, path);}public static void copy(File file, String path) throws E…

python RSA 加密与签名

PyCrypto装起来就简单多了&#xff0c;我是直接 sudo easy_install pycrypto 直接搞定的先生成rsa的公私钥&#xff1a;打开控制台&#xff0c;输入 openssl 再输入 genrsa -out private.pem 1024 来生成私钥接着输入 rsa -in private.pem -pubout -out public.pem 来生成公钥$…

深度解析VC中的消息(上)

消息是指什么&#xff1f;消息系统对于一个win32程序来说十分重要&#xff0c;它是一个程序运行的动力源泉。一个消息&#xff0c;是系统定义的一个32位的值&#xff0c;他唯一的定义了一个事件&#xff0c;向Windows发出一个通知&#xff0c;告诉应用程序某个事情发生了。例如…

漫谈C#之关键字(1)

每一种语言都有非常多的关键字&#xff0c;而且这些关键字也都大同小异&#xff0c;不过毕竟还是有些许的不一样。有些关键字大家碰到的多了&#xff0c;自然就熟悉了&#xff0c;但是有些关键字用得不大多&#xff0c;或者是新引入的&#xff0c;所以就不大熟悉了。我平常在用…

Python-CSS整理

CSS层叠样式表 1.格式 h1 {name:abc&#xff0c;color:red}&#xff1b; 选择器-属性-值 2.ID和类选择 #ID .类 3.CSS引用方式 link文件-外部样式表 script style-内部样式表 标签 style-内联样式 4.background背景 ~background ~-color 背景颜色 ~-repeat 是否重复 ~-pos…

利用 socket 获取 tcp 包并解析的问题。

服务器端代码如下&#xff1a;&#xff08;Java Servlet 实现&#xff09; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { OutputStream out response.getOutputStream(); try { …

Mysql排序后显示排序序号

网上找的一个比较齐全的解释案例&#xff0c;拿来记录一下 ① : 与 的区别 : 赋值的意思。在set update select 中表示赋值的意思&#xff0c;用的比较少一般都用&#xff0c;但是在用变量实现行号时&#xff08;比如本文标题获取排列序号&#xff09;&#xff0c;一定要用:…

解决Visual Studio For Mac Restore失败的问题

之前就了解到微软出了mac版的VS&#xff0c;没太多的关注&#xff0c;自己也就是使用 DotNet Core SDK VS Code 做一些小demo。 前两天发布了DotNet Core 2.0 &#xff0c;Visual Studio For Mac 7.1 之后&#xff0c;感觉可以装起来用用&#xff0c;把win下面的项目转到Core上…

应用Etherchannel扩展企业服务的高可用性

什么是Etherchannel&#xff1f;Etherchannel可以说是Cisco特有的技术&#xff0c;也就是我们在交换机以及路由器上所要配置Etherchannel就不得不使用CISCO设备。在实际工程中一般用于出口与上层设备的连接。实际上通过Etherchannel的中文名-端口绑定就很容易理解&#xff0c;它…

Leetcode 391.完美矩形

完美矩形 我们有 N 个与坐标轴对齐的矩形, 其中 N > 0, 判断它们是否能精确地覆盖一个矩形区域。 每个矩形用左下角的点和右上角的点的坐标来表示。例如&#xff0c; 一个单位正方形可以表示为 [1,1,2,2]。 ( 左下角的点的坐标为 (1, 1) 以及右上角的点的坐标为 (2, 2) )。…

Meteor计时器

Meteor有提供它自己的setTimeout和setInterval方法。这些方法被用于确保所有全局变量都具有正确的值。它们就像普通 JavaScript 中的setTimeout 和 setInterval 一样工作。Timeout - 超时 Meteor.setTimeout 的例子。Meteor.setTimeout(function(){console.log("Timeout c…

WEB程序代码优化入手的几方面

这里对web程序方面的优化作一个总结.1.编码规范化可读性优化编码规范我想一般程序员不会不了解&#xff0c;如果你这方面是空白你应该好好补补基础了&#xff0c;做到编码规范是一个好的程序员的最基础要求&#xff0c;一个团队也应该有自己的编码规范。所以程序的优化也应该包…

【Elastic Stack(一)】Elastic Stack简介

如果你没有听说过Elastic Stack&#xff0c;那你一定听说过ELK。实际上ELK是三款软件的简称&#xff0c;分别是Elasticsearch、Logstash、Kibana组成&#xff0c;在发展的过程中&#xff0c;又有新成员Beats的加入&#xff0c;所以就形成了Elastic Stack。 所以说&#xff0c;…

c#创建、保存excel正常执行要点补疑

网上搜索C#实现excel操作的示例太多了&#xff0c;但不知道有多少是经过验证确实可行才发布出来的&#xff0c;也是因为开发需要&#xff0c;我找了一些代码却发现大多都不能正确执行完毕&#xff0c;于是决定补充自己在实践中遇到的要点以供参考。如下示例&#xff1a;usingMi…

动态更新 AGS Cache

作者&#xff1a;Flyingis 提升ArcGIS Server访问速度最佳的方式是Cache&#xff0c;将所有图层切片保存在服务器&#xff0c;客户端请求时直接访问cache好的图片&#xff0c;这里分为两种情况&#xff0c;一是所有图层都做cache&#xff0c;二是部分图层做cache&#xff0…

SVN状态图标不显示的两种解决办法

文章目录第一种方法第二种方法首先情况如下&#xff1a;这样看不到状态是不是就很难受 本博主最近也是第一次使用SVN做版本控制 然后就出现了这样的情况后来经过查询才知道SVN刚下载安装后 设置什么的都是默认的 需要手动设置一下就OK啦 第一种方法 我们先在桌面或者资源管理…

SPOJ ATOMS - Atoms in the Lab

题目链接&#xff1a;http://www.spoj.com/problems/ATOMS/ 题目大意&#xff1a;有N个原子&#xff0c;他们每秒分裂成K个新原子&#xff0c;新原子也能继续分裂。问如果要控制他的数量为M以内&#xff0c;应在什么时候使其停止分裂。其实时间为0. 解题思路&#xff1a;可以发…

hive lock命令的使用

1.hive锁表命令 hive> lock table t1 exclusive;锁表后不能对表进行操作2.hive表解锁&#xff1a; hive> unlock table t1;3.查看被锁的表 1.hive> show locks; 转载于:https://www.cnblogs.com/liyanbin/p/10237482.html

技术类人员的职业发展的4大方向

几乎每个企业都需要技术员的支持&#xff0c;生产制造型企业需要现场生产控制和工艺流程方面的技术人才&#xff1b;it等高科技行业需要大量软件研发和设备维护的硬件工程师&#xff1b;房地产、建筑工程领域需要建筑设计师、土木工程师和施工技术人员。此外&#xff0c;不论是…

Injection of @Reference dependencies failed;

配置、注解、xml什么的所有东西都没有问题 可能是接口这边所应用的jar包版本太高了 尝试将对应的版本降低试一下就好了 我这边是dubbo的版本太高导致一直出现这种问题