集合(16):set接口的子类----TreeSet类


集合(16):set接口的子类----TreeSet类

1、TreeSet类的概述
元素唯一,元素的顺序可以按照某种规则进行排序
两种排序方式:
    	自然排序
   		比较器排序
2、TreeSet类的使用案例1
import java.util.TreeSet;
public class TreeSetDemo1 {
    public static void main(String[] args) {
        //创建一个集合对象
        TreeSet ts = new TreeSet<>();

        //添加元素到集合中
        ts.add(20);
        ts.add(18);
        ts.add(23);
        ts.add(24);
        ts.add(66);
        ts.add(12);
        ts.add(18);
        ts.add(20);
        ts.add(23);
        ts.add(2);

        //遍历
        for(Integer i : ts){
            System.out.println(i);
        }
    }
}
            执行结果如下:
                        2
                        12
                        18
                        20
                        23
                        24
                        66

                        Process finished with exit code 0
    //通过结果发现,TreeSet不仅去重,而且还重新排序了
3、查看源码,分析TreeSet为什么不仅去重,而且还重新排序

4、TreeSet类的使用案例2:TreeSet存储学生对象并遍历

第1步:需要定义一个学生类

第2步:

import java.util.TreeSet;
public class TreeSetDemo2 {
    public static void main(String[] args) {
        //创建集合对象
        TreeSet ts = new TreeSet<>();

        //创建学生对象
        Student3 s1 = new Student3("周姐",24);
        Student3 s2 = new Student3("李元浩",25);
        Student3 s3 = new Student3("李湘赫",22);
        Student3 s4 = new Student3("汉子哥",26);
        Student3 s5 = new Student3("硬币哥",21);
        Student3 s6 = new Student3("乌兹",20);
        Student3 s7 = new Student3("李元浩",25);
        Student3 s8 = new Student3("厂长",25);

        //将学生对象插入到集合中
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);
        ts.add(s6);
        ts.add(s7);
        ts.add(s8);

        for (Student3 s:ts){
            System.out.println(s);
        }
    }
}
//运行的时候报错
按照正常的写法,我们一运行就报错了
java.lang.ClassCastException:类型转换异常

通过源码可知,创建TreeSet对象调用的是无参构造方法,
走的是自然排序,而底层源码有一步向下转型
Comparable<? super K> k = (Comparable<? super K>) key;

报错的原因是我们Student3类没有实现Comparable接口,无法向下转型

回到第1步我们定义的学生类中来修改

//定义学生类的时候需要实现Comparable接口
//改进1处:
public class Student3 implements Comparable {
    private String name;
    private int age;

    public Student3() {
    }
    ...(此处省略)..

改进1后,还是会报错,是因为实现接口需要重写借口的所有方法,

我们少重写了接口中的comparableTo方法,需要添加进去

//改进2处:
public class Student3 implements Comparable {
    private String name;
    private int age;

    public Student3() {
    }
    ...(此处省略)..
        @Override
    public String toString() {
        return "Student2{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
//重写compareTo方法
    @Override
    public int compareTo(Student3 o) {
        return 0;
    }

在改进2处虽然重写了compareTo方法,但是在运行程序的时候,只打印了第一个对象

Student2{name='周姐', age=24}

Process finished with exit code 0

很显然,问题出在了返回值return 0;

如果return 1;打印结果如下:

Student2{name='周姐', age=24}
Student2{name='李元浩', age=25}
Student2{name='李湘赫', age=22}
Student2{name='汉子哥', age=26}
Student2{name='硬币哥', age=21}
Student2{name='乌兹', age=20}
Student2{name='李元浩', age=25}
Student2{name='厂长', age=25}

Process finished with exit code 0//return 1;没有去重

如果return -1;打印结果如下:

Student2{name='厂长', age=25}
Student2{name='李元浩', age=25}
Student2{name='乌兹', age=20}
Student2{name='硬币哥', age=21}
Student2{name='汉子哥', age=26}
Student2{name='李湘赫', age=22}
Student2{name='李元浩', age=25}
Student2{name='周姐', age=24}

Process finished with exit code 0//return 1;顺序全部颠倒

由此可知,返回值return 0; return 1; return -1;都不符合

需求:我想在去重的前提下,按照年龄进行排序,返回值为 return this.age - o.age;

输出结果如下:

Student2{name='乌兹', age=20}
Student2{name='硬币哥', age=21}
Student2{name='李湘赫', age=22}
Student2{name='周姐', age=24}
Student2{name='李元浩', age=25}
Student2{name='汉子哥', age=26}

Process finished with exit code 0
//年龄进行了排序,但是却把年龄相同的给去除了,不符合

最终的修改

@Override
    public int compareTo(Student3 o) {

        //年龄一样,姓名不一定一样
        //主要条件(题目要求的条件)
        int i = this.age - o.age;
        //隐含条件(需要自己挖掘)
        int i2 = i == 0 ? this.name.compareTo(o.name) : i;
        return i2;
    }
}

最终的运行结果:

Student2{name='乌兹', age=20}
Student2{name='硬币哥', age=21}
Student2{name='李湘赫', age=22}
Student2{name='周姐', age=24}
Student2{name='厂长', age=25}
Student2{name='李元浩', age=25}
Student2{name='汉子哥', age=26}

Process finished with exit code 0