• Java基础进阶TreeSet集合-Comparable,Comprator接口


    TreeSet集合中元素可排序有两种方式:

    • 第一种:实现Comparable接口
    • 第二种:使用Comparator比较器

    对于自定义的类型来说,TreeSet可以排序吗?

    以下程序中对于Person类型来说,无法排序。因为没有指定Person对象之间的比较规则

    谁大谁小并没有说明

    以下程序运行时出现ClassCastException异常

    出现异常的原因是:

    person类没有实现java.lang.Compareable接口

    public class TreeSetTest03 {
        public static void main(String[] args) {
    
            Person p1 = new Person(30);
            System.out.println(p1);
            Person p2 = new Person(20);
            Person p3 = new Person(22);
            Person p4 = new Person(25);
            Person p5 = new Person(38);
    
            //创建TreeSet集合对象
            TreeSet<Person> t = new TreeSet<>();
            t.add(p1);
            t.add(p2);
            t.add(p3);
            t.add(p4);
            t.add(p5);
    
            // 遍历
            for (Person p : t){
                System.out.println(p);
            }
    
        }
    }
    class Person{
    
        private int no;
    
        public Person(int no){
            this.no = no;
        }
    
        @Override
        public String toString() {
            return "Person[no="+no+"]";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    运行结果:

    在这里插入图片描述

    实现Comparable接口的例子:

    public class TreeSetTest04 {
        public static void main(String[] args) {
    
            Customer c1 = new Customer(30);
            Customer c2 = new Customer(20);
            Customer c3 = new Customer(22);
            Customer c4 = new Customer(25);
            Customer c5 = new Customer(38);
    
            //创建TreeSet集合对象
            TreeSet<Customer> Customers = new TreeSet<>();
            Customers.add(c1);
            Customers.add(c2);
            Customers.add(c3);
            Customers.add(c4);
            Customers.add(c5);
    
            // 遍历
            for (Customer c : Customers){
                System.out.println(c);
            }
        }
    }
    //放在TreeSet集合中的元素需要实现java.lang.Comparable
    //并且实现comparable方法。equals可以不写
    class Customer implements Comparable<Customer>{
    
        private int age;
    
        public Customer(int age) {
            this.age = age;
        }
    
        @Override
        //需要在这个方法中编写比较的逻辑,或者说比较的规则,按照什么进行比较!
        //k.compareTo(t.key)
        //拿着参数k和集合中的每一个k进行比较。,返回值可能是>0<0=0
        //比较规则最终还是由程序员指定的:例如按照年龄排序。或者按照年龄降序。
        public int compareTo(Customer c) {//c1.compareTo(c2)
           /*c1相当于this
           * c2相当于c
           * 比较的时候就是this和c的比较
           * */
            int age1 = this.age;
            int age2 = c.age;
           return age1 - age2;//升序
            //return age2 - age1;//降序
    
        }
    
        @Override
        public String toString() {
            return "Customer[age="+age+"]";
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    运行结果:

    在这里插入图片描述

    /*
    先按照年龄升序,如果年龄一样的再按照姓名升序。
     */
    public class TreeSetTest05 {
        public static void main(String[] args) {
    
            //创建集合对象
            TreeSet<Vip> Vips = new TreeSet<>();
            Vips.add(new Vip("lisi",18));
            Vips.add(new Vip("wangwu",20));
            Vips.add(new Vip("zhaoliu",20));
            Vips.add(new Vip("zhaosi",56));
            Vips.add(new Vip("guyi",35));
    
            for(Vip vip : Vips){
                System.out.println(vip);
            }
    
        }
    }
    class Vip implements Comparable<Vip>{
    
        private int age;
        private String name;
        public Vip(String name,int age){
            this.age = age;
            this.name = name;
        }
    
        @Override
    
        /*
        compareTo方法的返回值很重要:
            返回0表示相同,value会覆盖。
            返回>0,会继续在右子树上找。【10 - 9 = 1 ,1 > 0的说明左边这个数字比较大。所以在右子树上找。】
            返回<0,会继续在左子树上找。
         */
        public int compareTo(Vip v) {
            // 写排序规则,按照什么进行比较。
            if(this.age == v.age){
                // 年龄相同时按照名字排序。
                // 姓名是String类型,可以直接比。调用compareTo来完成比较。
                return this.name.compareTo(v.name);
            }else{
                return this.age - v.age;
            }
        }
    
        @Override
        public String toString() {
            return "Vip{" +
                    "age=" + age +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    运行结果:

    在这里插入图片描述

    TreeSet集合中元素可排序的第二种方式:使用比较器的方式。Comparator比较器

    public class TreeSetTest06 {
        public static void main(String[] args) {
    
            // 创建TreeSet集合的时候,需要使用这个比较器。
            // TreeSet wuGuis = new TreeSet<>();//这样不行,没有通过构造方法传递一个比较器进去。
    
            // 给构造方法传递一个比较器。
            //TreeSet wuGuis = new TreeSet<>(new WuGuiComparator());
    
            // 可以使用匿名内部类的方式(这个类没有名字。直接new接口。)
            TreeSet<WuGui> wuGuis = new TreeSet<>(new Comparator<WuGui>() {
                @Override
                public int compare(WuGui o1, WuGui o2) {
                    return o1.age - o2.age;
                }
            });
    
            wuGuis.add(new WuGui(20));
            wuGuis.add(new WuGui(30));
            wuGuis.add(new WuGui(10));
            wuGuis.add(new WuGui(25));
    
            for(WuGui wuGUi : wuGuis){
                System.out.println(wuGUi);
            }
    
        }
    }
    
    class WuGui {
    
        int age;
    
        public WuGui(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "WuGui{" +
                    "age=" + age +
                    '}';
        }
    }
    
    //不使用匿名内部类方式
    /*
    // 单独在这里编写一个比较器
    // 比较器实现java.util.Comparator接口。(Comparable是java.lang包下的。Comparator是java.util包下的。)
    class WuGuiComparator implements Comparator{
    
        @Override
        public int compare(WuGui o1, WuGui o2) {
            // 指定比较规则
            // 按照年龄排序
            return o1.age - o2.age;
        }
    
    }
    */
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    运行结果:

    在这里插入图片描述

    最终的结论:
    放到TreeSet或者TreeMap集合key部分的元素要想做到排序,包括两种方式:

    • 第一种:放在集合中的元素实现java.lang.Comparable接口。
    • 第二种:在构造TreeSet或者TreeMap集合的时候给它传一个比较器对象。

    Comparable和Comparator怎么选择呢?

    • 当比较规则不会发生改变的时候,或者说当比较规则只有1个的时候,建议实现Comparable接口。
    • 如果比较规则有多个,并且需要多个比较规则之间频繁切换,建议使用Comparator接口。
  • 相关阅读:
    【华为OD机试真题 JAVA】叠积木
    leetcode 1812
    C++笔试题复习
    软件测试工程师面试汇总功能测试篇
    Docker 部署mysql8(arm64)
    Java集合3-LinkedList
    洛谷P1506 拯救oibh总部 —DFS—围墙
    使用reposync同步远程yum源镜像仓库到本地和制作本地yum源(以同步EPEL为例)
    Failed to restart **: Unit **.service not found错误,
    7.1 C++ STL 非变易查找算法
  • 原文地址:https://blog.csdn.net/qq_46096136/article/details/126704870