解析treeSet集合进行自定义类的排序

解析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 另外会了三种就可以根据实际情况去选择合适的方法,而不是所有情况都用那么一种

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

SSS4362

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

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

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

打赏作者

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

抵扣说明:

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

余额充值