Java思考——如何使用Comparable按照我们指定的规则排序?
练习:
存储学生对象并遍历,创建TreeSet集合使用无参构造方法,并按照年龄从小到大的顺序排序,若年龄相同再按照姓名的字母顺序排序
分析:
1.创建学生类,成员变量name,age;无参构造,带参构造;get\set方法;
2.创建测试类,添加数据并进行排序;直接排序会报错
3.需要Student实现comparable接口并重写Comparable中的compareto方法来实现按照我们给定的顺序排序
Student类代码
public class Student{
//成员变量
private String name;
private int age;
//构造方法
public Student(){}
public Student(String name,int age){
this.age=age;
this.name=name;
}
//get\set方法
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;
}
}
测试类
public class StudentDemo {
public static void main(String[] args) {
//创建TreeSet对象
TreeSet<Student>ts=new TreeSet<Student>();
//创建学生对象
Student s=new Student("张三",18);
Student s1=new Student("张四",17);
Student s2=new Student("张五",19);
Student s3=new Student("张六",12);
//添加数据
ts.add(s);
ts.add(s1);
ts.add(s2);
ts.add(s3);
//遍历
for (Student ss:ts){
System.out.println(ss.getName()+ss.getAge());
}
}
}
第一次运行结果提示Student cannot be cast to java.lang.Comparable,这个时候我们就需要在Student类实现comparable接口重写compareto方法,并给定返回值
public class Student implements Comparable<Student>{
//成员变量
private String name;
private int age;
//构造方法
public Student(){}
public Student(String name,int age){
this.age=age;
this.name=name;
}
//get\set方法
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;
}
@Override
public int compareTo(Student o) {
// return 0;
// return 1;
// return-1;
}
}
那么可以看到compareto方法中有三个返回值分别是0、1、-1三种情况;
1.return 0:返回值是0的情况下再遍历集合只会在控制台打印出第一个元素;这是因为存入第一个元素时不需要比较直接存入集合,第二个 元素再存入是就需要跟第一个元素比较,但返回值为0,就会认为第二个元素跟第一个元素是相同的、重复的,就不存储,依此类推
2.return 1:返回值是1的情况下再遍历集合会按照存储数据的顺序在控制台全部打印出来;同样的,第一个元素存入不比较,第二个元素与第一个元素比较,返回值为1;就会认为第二个元素比第一个元素大,排在第一个元素后面,以此类推
3.return -1:与renturn 1的情况相反,也就是会按照存储数据顺序的倒序方式在控制台打印出来
思考:我们需要按照年龄的大小排序,这本质上不是只要返回值是一个正数就行了嘛,那我们就可以在compareto方法中这样写
public int compareTo(Student s) {
//return 0;
//return 1;
int num=this.age-s.age;
return num;
}
其中,this是方法内部就有的,在这里this.age代表当第一个元素存储后的后续每一个元素的年龄,我们用后续存储的元素年龄减去第一个元素的年龄当结果是-1时,就将该元素排在第一个元素前面,为1时,就排在后面,为0时就代表重复不存储
但是在我们完成按照年龄进行排序后有出现一个问题:当两个元素姓名不同年龄相同时,再按照我们设定的规则就不会将年龄相同的最后一个元素存储进去,因为它们两个年龄相减为0,默认重复了。所以在年龄相同的情况下,我们还要再比较姓名,如下
public int compareTo(Student s) {
//return 0;
//return 1;
int num=this.age-s.age;
int num1=num==0?this.name.compareTo(s.name):num;
return num1;
}
当年龄不同时返回的还是之前num的值,当年龄相同时比较姓名是否相同不相同返回1代表可以进行存储,相同返回0代表重复。
在这里因为string 本身就实现了comparable接口,所以可以直接调用compareto方法,这样就很好的解决了问题又保证了数据的唯一性
总结:
1.TreeSet集合存储自定义对象时,无参构造方法使用的是自然排序也就是按照存储元素的顺序进行排序
2.自然排序也就是让元素所属的类实现Comparable接口,重写compareto(T o)方法
3.重写compareto(T o)方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
Java思考——如何使用Comparable按照我们指定的规则排序?的更多相关文章
- java的Comparator和Comparable
java的Comparator和Comparable 当需要排序的集合或数组不是单纯的数字型时,通常可以使用Comparator或Comparable,以简单的方式实现对象排序或自定义排序. ...
- 1.java中Comparor与Comparable的问题
1.Comparator中compare()与Comparable中compareTo()方法的区别 Treeset集合创建对象后, A:如果是空构造,即TreeSet<Student> ...
- java源码之Comparable和Comparator
1,Comparable 简介 Comparable 是排序接口. 若一个类实现了Comparable接口,就意味着“该类支持排序”. 即然实现Comparable接口的类支持排序,假设现在存在“实 ...
- java.io.FileNotFoundException(系统找不到指定的路径。)
报错:java.io.FileNotFoundException(系统找不到指定的路径.) 解决方法: 1.检查文件路径是否正确 2.另外,使用OutputStream时,如果文件不存在,会自动创建文 ...
- java学习--自定义类的实例的大小比较和排序
我们知道Object类有一个equals方法,用于比较两个对象是否相等 我们只要在自定义类中重写了equals方法(若不重写就是比较两个实例的地址,相当于==)就可以用来比较该类的两个实例是否相等 问 ...
- 对JavaScript对象数组按指定属性和排序方向进行排序
引子 在以数据为中心的信息系统中,以表格形式展示数据是在常见不过的方式了.对数据进行排序是必不可少的功能.排序可以分为按单个字段排序和按多个字段不同排序方向排序.单字段排序局限性较大,不能满足用户对数 ...
- 组件注册-自定义TypeFilter指定过滤规则
组件注册-自定义TypeFilter指定过滤规则 4.1 FilterType.ANNOTATION 按照注解方式 4.2 FilterType.ASSIGNABLE_TYPE 按照给定的类型 @Co ...
- 4、组件注册-自定义TypeFilter指定过滤规则
4.组件注册-自定义TypeFilter指定过滤规则 4.1 FilterType.ANNOTATION 按照注解方式 4.2 FilterType.ASSIGNABLE_TYPE 按照给定的类型 @ ...
- sort如何按指定的列排序·百家电脑学院
sort如何按指定的列排序·百家电脑学院 sort如何按指定的(9php.com)列排序 0000 27189 41925425065f ...
随机推荐
- ASP.NET Core 6框架揭秘-实例演示版[持续更新中…]
作为<ASP.NET Core 3框架揭秘>的升级版,<ASP.NET Core 6框架揭秘>提供了很多新的章节,同时对现有的内容进行大量的修改.虽然本书旨在对ASP.NET ...
- netty介绍与构成
什么是 Netty Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架.Netty 提供高性能和可扩展性,让你可以自由地专注于你真 ...
- java 接口 文件传输
调用接收端 @ApiOperation(value = "文件请求展示方法") @RequestMapping(value = "/showFile", met ...
- Vue 源码解读(7)—— Hook Event
前言 Hook Event(钩子事件)相信很多 Vue 开发者都没有使用过,甚至没听过,毕竟 Vue 官方文档中也没有提及. Vue 提供了一些生命周期钩子函数,供开发者在特定的逻辑点添加额外的处理逻 ...
- [Matlab]三维曲面绘制实例
[x,y] = meshgrid(-8:0.5:8); z = sin(sqrt(x.^2+y.^2))./sqrt(x.^2+y.^2+eps); subplot(2,2,1); mesh(x,y, ...
- Json:Java对象和Json文本转换工具类
Json 是一个用于 Java 对象 和 Json 文本 相互转换的工具类. 安装 下载源码 git clone https://github.com/njdi/durian.git 编译源码 cd ...
- [旧][Android] Retrofit 初步使用
备注 原发表于2016.04.13,资料已过时,仅作备份,谨慎参考 Retrofit 是什么? Retrofit is a type-safe HTTP client for Android and ...
- MapReduce中一次reduce方法的调用中key的值不断变化
简单一句话总结就是:ReduceContextImpl类的RawKeyValueIterator input迭代器对象里面存储中着key-value对的元素, 以及一个只存储value的迭代器,然后每 ...
- 使用resize浏览器窗口大小改变事件容易出现的问题
1.使用jQuery的resize时间的时候发现每次改变浏览器窗口大小事resize事件会执行两次, 解决办法 var resizeTimer=null; $(window).resize(funct ...
- 串口通讯之rs232 c++版本
rs232.cpp #ifndef kranfix_rs232_rs232_cc #define kranfix_rs232_rs232_cc #include "rs232.h" ...