简介
之前的排序都是按照数据的某一个标准去排序,为了能够根据不同情景,按照数据不同标准去排序,自定义排序就应用而生。
情景
设计一个成绩排序,每位同学 都有自己的学号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)>0) && (compare(y, z)>0))</tt> implies
* <tt>compare(x, z)>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);
