当前位置:网站首页>解析treeSet集合进行自定义类的排序
解析treeSet集合进行自定义类的排序
2022-08-04 10:32:00 【SSS4362】
解析treeSet集合进行自定义类的排序
1 底层
1.1 treeSet是对传入的数据进行排序了,排序使用的方法是compareTo方法,add的加入的那个数相当于调用者
Integer里面的compareTo源码如下所示
public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}
//传入的数据就相当于你之前在集合里面的数据,很显然是String类型的数据,你把一个String类型传给Integer类型的形参,肯定会出现类型转换异常啊
//这个是运行时异常,出现异常时会生成一个异常对象,并抛出,运行时异常在编译期间是无需要进行处理的
1.2 排序要求所传入的数据类型必须相等(泛型去约束),不然就会出现classCastException异常
用到了多态(是用大的范围去接收),你本质是用Integer对象的数据,因此调用的是Integer里面的compareTo方法,因此若你在实参部分传入一个字符串类型,必然是会出现类型转换异常的
1.3 所有源码里面需要比较大小的类都实现了java.lang.Comparable接口
Integer类
String类
2.实现方法
2.1 实现Comparable接口
2.1.1 核心思路
a 自定义类需要实现Comparable接口并且重写compareTo方法
b compareTo方法通过this(调用者)和传入的参数进行合理的逻辑判断
一般是返回this.属性减去传入参数.属性 代表升序,反过来就是降序
如果是小数类型的比较的话,需要单独对>0和<1以及>-1小于0这两个情况进行判断
前一种返回正数(前大于后),后一种返回负数(前小于后),无论升序还是降序都是这样的,只需要去改前面的减法表达式就行
注意:自定义类可以不用实现equals方法也可以比较成功,因为它底层并没有调用equals方法去进行内容的比较,而是把对应的类型进行拆分逐个比较了,但是我们需要重写equals方法是因为可能其他的方法也需要调用它,并不是比较方法需要用到它
它是通过compareTo进行比较添加的,如果比较的那个属性值相等,不能返回0,随便返回-1或者1都行,返回-1代表插入的该数会返回到之前就存在的数字的前面,如果为1就代表插入的数会在相同数字的后面
c 只对一个属性进行排序的示例代码
Student类
package Work03;
import java.util.Objects;
public class Student{
private String name;
private int age;
private float degree;
//分数
public Student() {
}
public Student(String name, int age, float degree) {
this.name = name;
this.age = age;
this.degree = degree;
}
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 float getDegree() {
return degree;
}
public void setDegree(float degree) {
this.degree = degree;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", degree=" + degree +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Float.compare(student.degree, degree) == 0 && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, degree);
}
}
CompareDegree1类
package Work03;
import java.util.Comparator;
public class CompareDegree1 implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
//按照成绩去进行降序
float temp=o2.getDegree()-o1.getDegree();
//也可以写成>0返回正数,<=0返回负数,=0意味着插入的数字会在之前已经存在过的数据的上方
if (temp==0){
return 1;
}
if(temp>0&&temp<1){
return 1;
}else if(temp>-1&&temp<0){
return -1;
}
return (int)temp;
}
}
TestStudent02类
package Work03;
import java.util.Set;
import java.util.TreeSet;
public class TestStudent02 {
public static void main(String[] args) {
Set<Student> s=new TreeSet(new CompareDegree1());
s.add(new Student("马超",20,88.6f));
s.add(new Student("黄忠",22,77.7f));
s.add(new Student("李典", 20, 77.7f));
s.add(new Student("曹操",22,88.7f));
for (Student temp:s
) {
System.out.println(temp);
}
}
}
d 只对一个属性进行排序的示例代码代码运行截图
2.1.2 示例代码
Student类
package Work03;
import java.util.Objects;
public class Student implements Comparable<Student>{
private String name;
private int age;
private float degree;
//分数
public Student() {
}
public Student(String name, int age, float degree) {
this.name = name;
this.age = age;
this.degree = degree;
}
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 float getDegree() {
return degree;
}
public void setDegree(float degree) {
this.degree = degree;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", degree=" + degree +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Float.compare(student.degree, degree) == 0 && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, degree);
}
@Override
public int compareTo(Student o) {
//得不到想要的结果,一般是compareTo里面的逻辑判断出了问题
if(this.degree==o.degree){
//如果成绩相同,则需要再根据年龄进行排序
return this.age-o.age;
}else{
//降序需要倒过来,然后里面返回数值的正负和之前没关系
float temp=o.degree-this.degree;
if(temp>0&&temp<1){
return 1;
}
if(temp>-1&&temp<0){
return -1;
}
return (int)temp;
}
}
}
TestStudent02类
package Work03;
import java.util.Set;
import java.util.TreeSet;
public class TestStudent02 {
public static void main(String[] args) {
Set<Student> s=new TreeSet();
s.add(new Student("马超",20,88.6f));
s.add(new Student("黄忠",22,77.7f));
s.add(new Student("李典", 20, 77.7f));
s.add(new Student("曹操",22,88.9f));
for (Student temp:s
) {
System.out.println(temp);
}
}
}
2.1.3 示例代码运行截图
2.2 实现java.util.Comparator接口
2.2.1 核心思路
a 写一个自定义比较类实现java.util.Comparator接口
b 重写该接口里面的compare方法逻辑
c 然后在实例化treeSet对象的时候,丢入一个匿名自定义比较对象(里面含有排序规则)
d. 后面使用迭代器去进行遍历取出并打印里面的值即可
2.2.2 示例代码
Student类
package Work03;
import java.util.Objects;
public class Student{
private String name;
private int age;
private float degree;
//分数
public Student() {
}
public Student(String name, int age, float degree) {
this.name = name;
this.age = age;
this.degree = degree;
}
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 float getDegree() {
return degree;
}
public void setDegree(float degree) {
this.degree = degree;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", degree=" + degree +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Float.compare(student.degree, degree) == 0 && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, degree);
}
}
CompareDegree类
package Work03;
import java.util.Comparator;
public class CompareDegree implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
if(o1.getDegree()==o2.getDegree()){
//如果成绩一样,需要对年龄进行升序排序
return o1.getAge()-o2.getAge();
}else{
//返回值为int类型,但是可能需要强转,所以需要考虑减出来的结果是的绝对值结果是小数的情况
float temp=o2.getDegree()-o1.getDegree();
if(temp>0&&temp<1){
return 1;
}
if(temp>-1&&temp<0){
return -1;
}
return (int)temp;
}
}
}
TestDegree02类
package Work03;
import java.util.Set;
import java.util.TreeSet;
public class TestStudent02 {
public static void main(String[] args) {
Set<Student> s=new TreeSet(new CompareDegree());
s.add(new Student("马超",20,88.6f));
s.add(new Student("黄忠",22,77.7f));
s.add(new Student("李典", 24, 77.7f));
s.add(new Student("曹操",22,88.9f));
for (Student temp:s
) {
System.out.println(temp);
}
}
}
2.2.3 示例代码运行截图
2.3 用匿名内部类实现java.util.Comparator接口
2.3.1 核心思路
a 使用匿名内部类(这个类没有名字)去实现java.util.Comparator接口,(仅限于该对象去使用)
b.通过foreach循环取出并打印里面的每一个元素
2.3.2 示例代码
Student类
package Work03;
import java.util.Objects;
public class Student{
private String name;
private int age;
private float degree;
//分数
public Student() {
}
public Student(String name, int age, float degree) {
this.name = name;
this.age = age;
this.degree = degree;
}
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 float getDegree() {
return degree;
}
public void setDegree(float degree) {
this.degree = degree;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", degree=" + degree +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Float.compare(student.degree, degree) == 0 && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, degree);
}
}
TestDegree02类
package Work03;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class TestStudent02 {
public static void main(String[] args) {
Set<Student> s=new TreeSet(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//前面减去后面,升序,后面减去前面是降序,这里来个升序
float temp=o1.getDegree()-o2.getDegree();
if(temp==0){
//如果成绩相等就去比较年龄,按照年龄的升序去进行排列
//前减去后就是升序
return o1.getAge()-o2.getAge();
}
//大于0返回正数,小于0就返回负数,这个规则可以记一下
return temp>0?1:-1;
}
});
s.add(new Student("马超",20,88.6f));
s.add(new Student("黄忠",22,77.7f));
s.add(new Student("李典", 24, 77.7f));
s.add(new Student("曹操",22,88.9f));
for (Student temp:s
) {
System.out.println(temp);
}
}
}
2.3.3 示例代码运行截图
3.总结
3.1 尽量采用2.2这种采用类去实现Comparator接口这种方式。
3.1.1 理由
例如商品类里面有时需要根据价格排序,有时需要对销量进行排序,用另外两种每次都得改大量的代码,而采用类1实现价格排序,类2实现销量排序,new treeSet对象的时候根据需求去放入合适的类,这样无需进行代码的改动
3.2 虽然用非匿名内部类去实现Comparator接口(util包下面的)的方式比较多,但是另外两种也是要会的,
3.2.1 理由
a 方便看懂他人的代码
b 另外会了三种就可以根据实际情况去选择合适的方法,而不是所有情况都用那么一种
边栏推荐
猜你喜欢
参数优化文档介绍
Rust 入门指南 (用 WASM 开发第一个 Web 页面)
iMeta | Baidu certification is completed, search "iMeta" directly to the publisher's homepage and submission link
低代码是开发的未来吗?浅谈低代码开发平台的发展现状及未来趋势
小程序容器加快一体化在线政务服务平台建设
Jina 实例秀|基于神经搜索的网络安全威胁检测(一)
HTB-Sense
多媒体和物联网技术让版本“活”起来 129张黑胶唱片“百年留声”
2022 Cloud Native Computing代表厂商 | 灵雀云第三次入选Gartner中国ICT技术成熟度曲线报告
IDEA启动热部署
随机推荐
sqlilabs less-38~39
2022-08-03 第六小组 瞒春 学习笔记
密码字典生成工具pydictor/john
图文手把手教程--ESP32 一键配网(Smartconfig、Airkiss)
TCP协议 - 三次握手 - 四次挥手-内核参数调优
栈与队列的实现
一文带你了解 ESLint
小程序容器加快一体化在线政务服务平台建设
学习使用php把stdClass Object转array的方法整理
云计算适合什么企业_当前全球云计算处于发展
iMeta | Baidu certification is completed, search "iMeta" directly to the publisher's homepage and submission link
IDEA启动热部署
gom登录器配置教程_谷歌浏览器如何使用谷歌搜索引擎
Libtomcrypt AES 加密及解密
Multimedia and Internet of Things technology make the version "live" 129 vinyl records "Centennial Voice"
rk3399-339 usb设备复合 总体流程
[论文阅读] Unpaired Image-to-Image Translation Using Adversarial Consistency Loss
HCIP 第十八天
Qt:小的任务管理器(task)
mysql进阶(二十六)MySQL 索引类型