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 ...
随机推荐
- 我来教你如何用Docker部署最近火爆的人生重开模拟器
文章目录 获取项目源码包 Dockerfile 构建docker镜像 启动docerk容器 访问liferestart 如果人生可以重来... <可惜没如果> github项目地址:htt ...
- 面向对象—多态、鸭子类型(Day21)
编程原则java具有自己的编程原则和设计模式,不能多继承.python的编程原则:1.开放封闭原则:开放是对扩展是开放的,封闭是对修改是封闭的(已经写完的代码程序是不能修改的).2.依赖倒置原则:高层 ...
- unity3d导出xcode项目使用afnetworking 3框架导致_kUTTagClassMIMEType 问题解决方案
http://blog.csdn.net/huayu_huayu/article/details/51781953 (参考链接) Undefined symbols for architecture ...
- [LeetCode]LCP 01. 猜数字
小A 和 小B 在玩猜数字.小B 每次从 1, 2, 3 中随机选择一个,小A 每次也从 1, 2, 3 中选择一个猜.他们一共进行三次这个游戏,请返回 小A 猜对了几次? 输入的guess数组为 小 ...
- MySQL 8.0.25 MSI Install 安装过程
官网下载地址: https://dev.mysql.com/downloads/mysql 其中web-community需要联网安装,另外一个可以离线安装.我下载的是离线安装包. 1.双击安 ...
- 无法将具有语句体的lambda表达式转换为表达式树
很早就碰到了这个问题,当时也没有深入的研究,趁着空闲,遂把这个问题研究清楚. (一)普通案例 下面从一个普通的案例入手,下面准备两个List集合,都是放在内存里面的(需要模拟到远端执行的时候,我们是通 ...
- selenium+python自动化104-如何获取隐藏元素text文本
前言 首先 selenium 是可以定位到隐藏元素的,但是 selenium 不能跟隐藏元素交互,也就是隐藏元素element不能使用element.click()方法. 隐藏元素element.te ...
- Python:使用piecewise与curve_fit进行三段拟合
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ,11, 12, 13, 14, 15,16,17,18,19,20,21], dtype=float) y = ...
- petite-vue源码剖析-属性绑定`v-bind`的工作原理
关于指令(directive) 属性绑定.事件绑定和v-modal底层都是通过指令(directive)实现的,那么什么是指令呢?我们一起看看Directive的定义吧. //文件 ./src/dir ...
- Spring入门一:IOC、DI、AOP基本思想
Spring框架是一个集众多涉及模式于一身的开源的.轻量级的项目管理框架,致力于javaee轻量级解决方案.相对于原来学过的框架而言,spring框架和之前学习的struts2.mybatis框架有了 ...