java的Comparator<T>接口在实现集合内元素排序时的用法(个人思考&案例分析)

一、案例Demo

先上一段代码(出自黑马程序员在B站的java基础课程)

public class Demo_Student {
    public static void main(String[] args) {
        Student s1 = new Student("张三" , 100 , 98);
        Student s2 = new Student("李四" , 80 , 95);
        Student s3 = new Student("王五" , 96 , 92);
        Student s4 = new Student("赵六" , 99 , 99);
        
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int num = s2.getTotal() - s1.getTotal();//降序排列
                num = (num == 0) ? s1.getName().compareTo(s2.getName()) : num;
                return num;
            }
        });
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);

        for (Student stu : ts){
            System.out.println(stu.getName() + " 总分:" + stu.getTotal() + 
            " 语文:" + stu.getChineseScore() + " 数学:" + stu.getMathScore());
        }
    }
}
  • Demo基本的功能:
    1、将Student对象装入TreeSet集合中;
    2、对集合内部的Student对象元素进行自定义排序规则的排序;
    3、输出排序后的集合元素。

二、案例解析

  • 对于上述提及的,Demo的三个部分的功能,最关键的毫无疑问是第②步,如何对TreeSet集合内部的Student对象元素进行自定义规则的排序。
  • 所以这里就涉及到:创建TreeSet对象的时候,new Comparator< T >()对象,并重写其compare()方法
  • 而实现自定义规则排序的关键,就是重写Comparator接口的compare()方法

三、compare方法的剖析(重)

以Demo为例:首先根据总成绩(getTotal)降序排序,即从大到小;如果总分相同,则按照姓名的字母顺序,由小到大排序。那么应该怎样设计重写compare方法呢?

在这里插入图片描述


对于重写compare(),有两点理解至关重要:①两个参数o1 o2int类型的返回值

@Override
public int compare(Student s1, Student s2) {
	//Demo中仅仅是将参数名修改为s1 s2,不影响功能
    int num = s2.getTotal() - s1.getTotal();
    num = (num == 0) ? s1.getName().compareTo(s2.getName()) : num;
    return num;
}
1、参数o1 o2(s1 s2),代表了在集合中顺序存储着的两个元素,o1在前,o2在后。
2、int类型的返回值,如果为正值,则在集合中对o1 o2的位置进行互换;为负则保持不变。(正则为真,执行互换;负责为假,不予执行)
  • 第一行语句:s2的总分与s1的总分相减,赋值给num;如果就此打住,紧接着return,那么如果s2更大,则num为正,返回值为正,s1 s2交换,大的元素永远在前;如果s2更小,num为负,s1 s2不交换,完成成绩的降序排序!
  • 第二行语句:如果s1 s2总分相同(如张三和赵六),则num根据s1 s2的姓名比较结果进行排序。注:compareTo:左小右大为负,右大左小为正,左右相等为零;至此,完成姓名升序排序!

四、总结

简而言之:compare内部不管做了多么复杂的运算,制定了多么复杂的规则,最后排序的结果(o1 o2是否交换)永远只取决于返回值的正负情况,所以在设计我们自己的集合排序规则的时候,这也是我们考虑的最核心问题。

五、一些拓展

1、类似的,通过new Comparator接口并重写其compare方法的方式,完成自定义排序的其他几种情况(个人经验,并不全面):

  • ArrayList的sort()方法:(巩固例题)

ArrayList对象名.sort(new Comparator< T >(){ … });

  • Collections.sort()方法:

Collections.sort(List< T > list,Comparator<? super T> c);

  • Arrays.sort()方法:

Arrays.sort(T[] a,Comparator<? super T> c);

2、巩固例题:算法提高 最小字符串

  • 问题描述
    给定一些字符串(只包含小写字母),要求将他们串起来构成一个字典序最小的字符串。

  • 输入格式
    第一行T,表示有T组数据。
    接下来T组数据
    每组第一行一个正整数n,表示字符串个数。
    接下来n行,每行一个字符串(长度不超过100)。

  • 输出格式
    T行,每行一个字符串。

  • 样例输入
    1
    3
    a
    b
    c

  • 样例输出
    abc

代码如下:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();//总共的字符串数

        for (int i = 0 ; i < n ; i++){
            int num = sc.nextInt();//接下来输入几行
            ArrayList<String> list = new ArrayList<String>();//使用ArrayList存储所有输入的字符
            for (int j = 0 ; j < num ; j++){
                String str = sc.next();
                list.add(str);//将字符装入List
            }

            list.sort(new Comparator<String>() {//调用ArrayList的sort()方法并且重写Comparator
                @Override
                public int compare(String o1, String o2) {
					//例如:b和ba,字典序b<ba,但是从大局考虑,ba应排在前面
                    String temp1 = o1 + o2;
                    String temp2 = o2 + o1;//代表 “o2在前,o1在后” 的状态
                    //若返回负数,则不交换,o1 o2目前状态(o1前o2后)满足整体字符串的字典序最小
                    return temp1.compareTo(temp2);
                }
            });

            for (int j = 0 ; j < num ; j++){//输出一组字符串
                System.out.print(list.get(j));
            }
            System.out.println();

        }

        sc.close();
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是使用`Comparator`接口实现分数排序的示例代码: 假设有一个`Student`类,其中包含学生的姓名和分数信息: ```java public class Student { private String name; private int score; public Student(String name, int score) { this.name = name; this.score = score; } public String getName() { return name; } public int getScore() { return score; } } ``` 现在,我们可以使用`Comparator`接口实现按照分数从高到低排序。示例代码如下: ```java import java.util.*; public class ScoreSorter { public static void main(String[] args) { List<Student> students = new ArrayList<>(); students.add(new Student("Alice", 90)); students.add(new Student("Bob", 80)); students.add(new Student("Charlie", 70)); students.add(new Student("David", 85)); // 使用 Comparator 接口实现分数排序 Collections.sort(students, new Comparator<Student>() { @Override public int compare(Student s1, Student s2) { return s2.getScore() - s1.getScore(); } }); // 输出排序结果 for (Student student : students) { System.out.println(student.getName() + " : " + student.getScore()); } } } ``` 在上面的代码中,我们使用`Collections.sort`方法对学生列表进行排序,第二个参数传入一个实现了`Comparator`接口的匿名内部类。在该匿名内部类中,我们实现了`compare`方法来比较两个学生的分数大小,从而实现分数从高到低排序。 注意,这里的`compare`方法返回的是正数、负数或0,用于表示两个元素的相对大小关系。如果返回正数,表示`s2`大于`s1`;如果返回负数,表示`s1`大于`s2`;如果返回0,表示`s1`和`s2`相等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值