针对Java中对象数组排序问题,Java中提供两种实现方式。
- 实现Comparable接口方式(自然排序);
- 实现Comparator接口方式(定制排序);
1. 自然排序和定制排序的异同点:
自然排序:需要进行排序的类实现Comparable接口,并且重写compareTo方法,compareTo方法只有一个参数,。
定制排序:需要在需要排序的类之外再定义一个类实现Comparator接口,并且重写compare方法,compare方法有两个参数。
相同点:compareTo和compare方法返回值都是int类型,并且方法内部比较的两个对象,大于返回正数,小于则返回负数,如果相等则返回0.
2. 实现代码:
自然排序实例:
学生实体类:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student implements Comparable<Student>{
private String studentName;
private int score;
@Override
public int compareTo(Student o) {
//根据学生分数进行增序排序,在两个学生分数相同情况下,根据学生姓名进行升序排序
if(this.score > o.score){
return 1;
}else if (this.score < o.score){
return -1;
}else {
return this.studentName.compareTo(o.studentName);
}
}
}
测试方法:
@Test
public void test01(){
Student[] students = new Student[5];
students[0] = new Student("王二",84);
students[1] = new Student("张三",89);
students[2] = new Student("李四",60);
students[3] = new Student("王五",93);
students[4] = new Student("赵六",84);
Arrays.sort(students);
System.out.println(Arrays.toString(students));
}
测试结果:
[Student(studentName=李四, score=60), Student(studentName=王二, score=84), Student(studentName=赵六, score=84), Student(studentName=张三, score=89), Student(studentName=王五, score=93)]
定制排序实例:
定制排序比较器:
public class StudentComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
//根据学生分数,进行降序排列,如果学生分数相等根据人员姓名进行降序排列。
if(o1.getScore() > o2.getScore()){
return -1;
}else if (o1.getScore() < o2.getScore()){
return 1;
}else {
return -o1.getStudentName().compareTo(o2.getStudentName());
}
}
}
测试方法:
@Test
public void test02(){
Student[] students = new Student[5];
students[0] = new Student("王二",84);
students[1] = new Student("张三",89);
students[2] = new Student("李四",60);
students[3] = new Student("王五",93);
students[4] = new Student("赵六",84);
Arrays.sort(students,new StudentComparator());
System.out.println(Arrays.toString(students));
}
测试结果:
[Student(studentName=王五, score=93), Student(studentName=张三, score=89), Student(studentName=赵六, score=84), Student(studentName=王二, score=84), Student(studentName=李四, score=60)]
对于定制排序需要另外定义一个类作为比较器,我们可以使用匿名实现类,从而不需要再另外定义一个类。所以定制排序的另一种写法如下代码显示(也可以简化使用lambda表达式):
@Test
public void test03(){
Student[] students = new Student[5];
students[0] = new Student("王二",84);
students[1] = new Student("张三",89);
students[2] = new Student("李四",60);
students[3] = new Student("王五",93);
students[4] = new Student("赵六",84);
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
if(o1.getScore() > o2.getScore()){
return -1;
}else if (o1.getScore() < o2.getScore()){
return 1;
}else {
return -o1.getStudentName().compareTo(o2.getStudentName());
}
}
});
System.out.println(Arrays.toString(students));
}
集合中使用到的自然排序和定制排序:
Collections.sort(List< T> list);(可实现自然排序);
Collections.sort(List< T> list,Comparator<? super Object> c);
TreeMap中自然排序:
@Test
public void test06(){
TreeMap<Student,Integer> treeMap = new TreeMap<>();
treeMap.put(new Student("王二",84),49);
treeMap.put(new Student("张三",89),54);
treeMap.put(new Student("李四",60),44);
treeMap.put(new Student("王五",93),62);
treeMap.put(new Student("赵六",84),21);
Iterator<Map.Entry<Student, Integer>> iterator = treeMap.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<Student,Integer> map = iterator.next();
System.out.println(map.getKey() + "------->" + map.getValue());
}
}
测试结果:
Student(studentName=李四, score=60)------->44
Student(studentName=王二, score=84)------->49
Student(studentName=赵六, score=84)------->21
Student(studentName=张三, score=89)------->54
Student(studentName=王五, score=93)------->62
TreeMap中定制排序:
@Test
public void test07(){
TreeMap<Student,Integer> treeMap = new TreeMap<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
if(o1.getScore() > o2.getScore()){
return -1;
}else if (o1.getScore() < o2.getScore()){
return 1;
}else {
return o1.getStudentName().compareTo(o2.getStudentName());
}
}
});
treeMap.put(new Student("王二",84),49);
treeMap.put(new Student("张三",89),54);
treeMap.put(new Student("李四",60),44);
treeMap.put(new Student("王五",93),62);
treeMap.put(new Student("赵六",84),21);
Iterator<Map.Entry<Student, Integer>> iterator = treeMap.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<Student,Integer> map = iterator.next();
System.out.println(map.getKey() + "------->" + map.getValue());
}
}
测试结果:
Student(studentName=王五, score=93)------->62
Student(studentName=张三, score=89)------->54
Student(studentName=王二, score=84)------->49
Student(studentName=赵六, score=84)------->21
Student(studentName=李四, score=60)------->44
3. 优缺点:
自然排序实现Comparable接口比较简单,不需要另外定义一个比较器类,但要修改进行比较类的原有代码。定制排序实现Comparator接口需要另外定义一个类,作为比较器,比较复杂,但实现不需要对原代码修改,只需要另外定义比较规则的类即可。