简介

之前的排序都是按照数据的某一个标准去排序,为了能够根据不同情景,按照数据不同标准去排序,自定义排序就应用而生。

情景

  1. 设计一个成绩排序,每位同学 都有自己的学号ID,名字name , 语文成绩chineseGrade,数学成绩mathGrade,英语成绩englishGrade以及自己的总成绩totalGrade<br /> 要求排序规则为如下:<br /> 1】总成绩不相等,按照总成绩降序<br /> 2】总成绩相等,按照数学成绩降序<br /> 3】数学成绩相等,按照英语成绩降序<br /> 4】英语成绩相等,按照名字首字母降序<br /> 5】首字母相等,按照学号降序

代码

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Solution {

    private static class Student {
        int id;//学号
        String name;//名字
        int chineseGrade;//语文成绩
        int mathGrade;//数学成绩
        int englishGrade;//英语成绩
        int totalGrade;//总成绩

        Student(int id, String name, int chineseGrade, int mathGrade, int englishGrade) {
            this.id = id;
            this.name = name;
            this.chineseGrade = chineseGrade;
            this.mathGrade = mathGrade;
            this.englishGrade = englishGrade;
            this.totalGrade = 100;
        }
    }

    /**
     * 排序规则 :
     * [1] 总成绩降序;
     * [2] 总成绩相同的情况下,数学成绩降序,
     * [3] 数学成绩相同的情况下,英语成绩降序
     * [4] 英语成绩相同的情况下, 名字首字母降序
     * [5] 首字母相同的情况下, 学号ID,升序排列;
     *
     * @param studentList
     * @return
     */
    public List<Student> gradeSort(List<Student> studentList) {
        studentList.sort((stu1, stu2) -> {
            //总成绩相同的情况下,数学成绩降序,
            if (stu1.totalGrade == stu2.totalGrade) {
                //数学成绩不等;
                if (stu1.mathGrade != stu2.mathGrade) {
                    return stu2.mathGrade - stu1.mathGrade;
                } else {
                    //英语成绩不相等的情况下,降序;
                    if (stu1.englishGrade != stu2.englishGrade) {
                        return stu2.englishGrade - stu1.englishGrade;
                    } else {
                        //名字首字母不相等的情况下,首字母按照字典序倒序;
                        if (stu1.name.charAt(0) != stu2.name.charAt(0)) {
                            return stu2.name.charAt(0) - stu1.name.charAt(0);
                        } else {
                            //如果首字母相等的情况下,则按照学号ID,升序
                            return stu1.id - stu2.id;
                        }
                    }
                }
            }
            //默认按照总成绩排序;
            return stu2.totalGrade - stu1.totalGrade;
        });
        return studentList;
    }

    /**
     * 生成随机名字;
     *
     * @return
     */
    private static String randomGenerateName(int length) {
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(62);
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }

    /**
     * 生成随机成绩;
     *
     * @return
     */
    private static int randomGenerateGrade() {
        Random random = new Random();
        int randomGrade = random.nextInt(100);
        return randomGrade;
    }

    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        for (int i = 0; i < 10; ++i) {
            list.add(new Student(i, randomGenerateName(i + 3), randomGenerateGrade(), randomGenerateGrade(), randomGenerateGrade()));
        }
        list = new Solution().gradeSort(list);
        for (Student student : list) {
            System.out.println("ID:" + student.id + " name:" + student.name + " chineseGrade: " + student.chineseGrade + " mathGrade: " + student.mathGrade
                    + " englishGrade:" + student.englishGrade + " totalGrade:" + student.totalGrade);
        }
    }
}

分析

基于Comparator接口的排序

Comparator接口可以实现自定义排序,实现Comparator接口时,要重写compare方法:
int compare(Object o1, Object o2) 返回一个基本类型的整型
如果要按照升序排序,则o1 小于o2,返回-1(负数),相等返回0,01大于02返回1(正数) return o1-o2;
如果要按照降序排序,则o1 小于o2,返回1(正数),相等返回0,01大于02返回-1(负数) return o2-o1;
`    /**
     * 如果第一个参数小于第二个参数,返回负数
     * 如果第一个参数等于第二个参数,返回0
     * 如果第一个参数大于第二个参数,返回正数
     * Compares its two arguments for order.  Returns a negative integer,
     * zero, or a positive integer as the first argument is less than, equal
     * to, or greater than the second.<p>
     *
     * In the foregoing description, the notation
     * <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
     * <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
     * <tt>0</tt>, or <tt>1</tt> according to whether the value of
     * <i>expression</i> is negative, zero or positive.<p>
     *
     * The implementor must ensure that <tt>sgn(compare(x, y)) ==
     * -sgn(compare(y, x))</tt> for all <tt>x</tt> and <tt>y</tt>.  (This
     * implies that <tt>compare(x, y)</tt> must throw an exception if and only
     * if <tt>compare(y, x)</tt> throws an exception.)<p>
     *
     * The implementor must also ensure that the relation is transitive:
     * <tt>((compare(x, y)&gt;0) &amp;&amp; (compare(y, z)&gt;0))</tt> implies
     * <tt>compare(x, z)&gt;0</tt>.<p>
     *
     * Finally, the implementor must ensure that <tt>compare(x, y)==0</tt>
     * implies that <tt>sgn(compare(x, z))==sgn(compare(y, z))</tt> for all
     * <tt>z</tt>.<p>
     *
     * It is generally the case, but <i>not</i> strictly required that
     * <tt>(compare(x, y)==0) == (x.equals(y))</tt>.  Generally speaking,
     * any comparator that violates this condition should clearly indicate
     * this fact.  The recommended language is "Note: this comparator
     * imposes orderings that are inconsistent with equals."
     *
     * @param o1 the first object to be compared.
     * @param o2 the second object to be compared.
     * @return a negative integer, zero, or a positive integer as the
     *         first argument is less than, equal to, or greater than the
     *         second.
     * @throws NullPointerException if an argument is null and this
     *         comparator does not permit null arguments
     * @throws ClassCastException if the arguments' types prevent them from
     *         being compared by this comparator.
     */
    int compare(T o1, T o2);