在编写Java代码时,常常会用到自定义排序。
例如,有一些学生,学生有分数score
、num
两个属性。我们需要根据学生的分数作降序排序(即分数高的在前面)。如果分数相同,需要按照年龄作升序(即年龄高的在后面)。
class Student{
int score;
int age;
Student(int score, int age){
this.score = score;
this.age = age;
}
public int getScore() {return score;}
public void setNum(int score) {this.score = score;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
对下列学生集合进行排序:
public static void main(String[] args) {
Student stu[] = new Student[3];
stu[0] = new Student(1,2);
stu[1] = new Student(1,0);
stu[2] = new Student(2,0);
}
1、通过重写Comparator的compare方法:
Arrays.sort(stu, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
if(o1.getScore() != o2.getScore())
return o2.getScore() - o1.getScore();
return o1.getAge() - o2.getAge();
}
});
改写成lambda形式:
Arrays.sort(stu, ((o1, o2) -> {
if(o1.getScore() != o2.getScore())
return o2.getScore() - o1.getScore();
return o1.getAge() - o2.getAge();
}));
Arrays.sort(stu, Comparator.comparing(Student::getScore)
.reversed()
.thenComparing(Student::getAge));
上面的方法我比较常用的是重写Comparator的compare方法(lambda形式)。在写算法题时经常遇到需要对一个“宽”为2的二维数组进行排序(按照下标0
或1
),例如:
int a[][] = {{1,2},
{1,0},
{2,0}};
很容易就可以写出:
Arrays.sort(a, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
if(o2[0] != o1[0])
return o2[0] - o1[0];
return o1[1] - o2[1];
}
});
Arrays.sort(a, (o1, o2) -> {
//第一位降序
if(o2[0] != o1[0])
return o2[0] - o1[0];
return o1[1] - o2[1];
});
这是二维数组的情况,倘若想对一维数组作排序,我们可以照葫芦画瓢:
int b[] = {1,3,4,3,6,7};
Arrays.sort(b, (o1, o2)-> o2 - o1);
这时发现报错了:
与上面对二维数组与学生进行排序不同,这里Comparator接收的是基本数据类型int,但是是不支持的,因为接收参数定义了泛型,只能接收引用类型的参数,进而改写的lambda形式也同样报错:
若执意要对一维数组进行自定义排序,那么我们需要保证数组内存的值不是基本数据类型的,而是引用数据类型的。
Integer c[] = {1,3,4,3,6,7};
Arrays.sort(c, (o1, o2)-> o2 - o1);
即对于一维数组b,需要将其“装箱”进行自定义排序,排完序再“拆箱”:
int b[] = {1,3,4,3,6,7};
Integer b1[] = Arrays.stream(b).boxed().toArray(Integer[]::new);
Arrays.sort(b1, (o1, o2)-> o2 - o1);
b = Arrays.stream(b1).mapToInt(Integer::intValue).toArray();