Set集合的直接子类TreeSet

ndmtzwdx / 2024-10-21 / 原文

一、TreeSet:

底层数据结构是红黑树(自平衡二叉树),具备了可预测的排序

1.自然排序

通过实现comparable接口,重写里面的compareTo方法来进行排序

1.编写一个Dog类,实现了Comparable接口,并重写里面的方法

public class Dog implements Comparable<Dog>{
    private String name;
    private int age;

    public Dog() {
    }

    public Dog(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;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Dog o) {
        // this - 待插入元素
        // o - 要比较的根元素
        //当姓名和年龄一样的时候去重,年龄需要从小到大排序
        //return this.age - o.getAge();
        //显式条件
        int i=this.age-o.getAge();
        //隐式条件
        //当年龄一样的时候,姓名不一定一样
        return (i==0)?this.name.compareTo(o.getName())   :i;
    }
}

2.测试类

import java.util.TreeSet;

public class TreeSetDemo2 {
    public static void main(String[] args) {
        TreeSet<Dog> treeSet = new TreeSet<>();
        Dog d1 = new Dog("煤球",3);
        Dog d2 = new Dog("旺财",2);
        Dog d3 = new Dog("小灰",3);
        Dog d4 = new Dog("煤球",3);
        Dog d5 = new Dog("白线",4);

        treeSet.add(d1);
        treeSet.add(d2);
        treeSet.add(d3);
        treeSet.add(d4);
        treeSet.add(d5);
        //当传入一个对象的成员变量值的时候,我们要实现Comparable接口,并重写compareTo方法,里面的内容决定按照什么排序
        System.out.println(treeSet);
    }
}

2.比较器排序

可以不实现comparable接口,传递一个 Comparator 对象

1.先编写一个Dog1类

package com.day14;

public class Dog1 {
    private String name;
    private int age;

    public Dog1() {
    }

    public Dog1(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;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2.再编写测试类

import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo3 {
    public static void main(String[] args) {
        //使用比较器排序,匿名内部类
        TreeSet<Dog1> treeSet = new TreeSet<>(new Comparator<Dog1>() {
            @Override
            public int compare(Dog1 o1, Dog1 o2) {
                int i=o1.getAge()- o2.getAge();
                return (i==0)?o1.getName().compareTo(o2.getName()):i;
            }
        });
        Dog1 d1 = new Dog1("煤球",3);
        Dog1 d2 = new Dog1("旺财",2);
        Dog1 d3 = new Dog1("小灰",3);
        Dog1 d4 = new Dog1("煤球",3);
        Dog1 d5 = new Dog1("白线",4);


        treeSet.add(d1);
        treeSet.add(d2);
        treeSet.add(d3);
        treeSet.add(d4);
        treeSet.add(d5);
        //当传入一个对象的成员变量值的时候,我们要实现Comparable接口,并重写compareTo方法,里面的内容决定按照什么排序
        System.out.println(treeSet);
    }

}

二、TreeSet的练习题:

键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台

1.先编写一个学生类,注意一下这个学生类我们需要编写一个方法用来获取总分

public class Student2 {
    //姓名,语文成绩,数学成绩,英语成绩
    private String name;
    private int chinese;
    private int math;
    private int english;

    public Student2() {
    }

    public Student2(String name, int chinese, int math, int english) {
        this.name = name;
        this.chinese = chinese;
        this.math = math;
        this.english = english;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getChinese() {
        return chinese;
    }

    public void setChinese(int chinese) {
        this.chinese = chinese;
    }

    public int getMath() {
        return math;
    }

    public void setMath(int math) {
        this.math = math;
    }

    public int getEnglish() {
        return english;
    }

    public void setEnglish(int english) {
        this.english = english;
    }

    public int getSumScore() {
        return chinese + math + english;
    }

    @Override
    public String toString() {
        return "Student2{" +
                "name='" + name + '\'' +
                ", chinese=" + chinese +
                ", math=" + math +
                ", english=" + english +
                '}';
    }
}

2.编写测试类,这个测试类需要去进行排序,按照年龄的大小,这里使用比较器排序,就不用实现comparable接口,重写里面的方法

public class TreeSetTest1 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        //创建一个TreeSet集合
        TreeSet<Student2> set1 = new TreeSet<>(new Comparator<Student2>() {
            @Override
            public int compare(Student2 o1, Student2 o2) {
                //显式条件:按照总分从高到低输出到控制台
                int i1 = o2.getSumScore() - o1.getSumScore();
                //隐式条件
                //总分一样,语文成绩不一定一样
                int i2 = (i1 == 0) ? o2.getChinese() - o1.getChinese() : i1;
                //总分一样,语文成绩一样,数学成绩不一定一样
                int i3 = (i2 == 0) ? o2.getMath() - o1.getMath() : i2;
                //各科成绩一样,姓名不一定一样
                return (i3 == 0) ? o2.getName().compareTo(o1.getName()) : i3;
            }
        });

        for(int i=1;i<=5;i++){
            System.out.println("请输入第 "+i+" 个学生的信息");
            System.out.print("请输入姓名: ");
            String name = sc.next();
            System.out.print("请输入该学生的语文成绩: ");
            int chinese = sc.nextInt();
            System.out.print("请输入该学生的数学成绩: ");
            int math = sc.nextInt();
            System.out.print("请输入该学生的英语成绩: ");
            int english = sc.nextInt();
            set1.add(new Student2(name,chinese,math,english));
        }

        System.out.println("学生信息录入完毕!!");
        System.out.println("================= 学生成绩汇总 ===================");
        System.out.println("姓名\t\t语文成绩\t\t数学成绩\t\t英语成绩\t\t总分");
        //遍历集合
        for (Student2 student2 : set1) {
            System.out.println(student2.getName()+"\t\t"+
                    student2.getChinese()+"\t\t"+
                    student2.getMath()+"\t\t"+
                    student2.getEnglish()+"\t\t"+
                    student2.getSumScore());
        }


    }
}