Java中比较器是排序、加入有序数组等操作的时候必须要有的,没有的话会报错,例如下面这段代码:
package dataStructure.heap;
import java.util.Arrays;
import java.util.Comparator;
import java.util.TreeMap;
public class MyComparatorTest {
public static void main(String[] args) {
Student[] students = {new Student(2, "student2", 20),
new Student(2, "student3", 30), new Student(4, "student4", 40)};
//这里如果只写students数组而不传入比较器的话会报错
Arrays.sort(students);
}
}
class Student {
int age;
String name;
int id;
public Student(int age, String name, int id) {
this.age = age;
this.name = name;
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
运行时会发生下面的异常
Exception in thread "main" java.lang.ClassCastException: dataStructure.heap.Student cannot be cast to java.lang.Comparable
at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:320)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:188)
at java.util.Arrays.sort(Arrays.java:1246)
at dataStructure.heap.MyComparatorTest.main(MyComparatorTest.java:13)
Process finished with exit code 1
这个sort方法是可以只传入数组(数组中的类型是基础类型或者已经实现了Comparable了),也可以传入两个参数:数组和数组中类型的比较器
比较器实现有两种方式,
一种是当前类实现了java.lang.Comparable接口,这个时候当前类需要实现下面这个方法:
@Override public int compareTo(Object o) { return 0; }
这种方式只有一种比较方式,比较死板,一般我不会使用(虽然也可以叠加比较器,叠加比较器的时候相当于这是一种默认的,传了使用比较器,没有传使用这个)
第二种方式是:写一个比较器类继承Comparator,范型是当前类型(也可以不写比较器类而在使用的时候直接传入Lambda表达式)
改造之后的类如下:
package dataStructure.heap;
import java.util.Arrays;
import java.util.Comparator;
import java.util.TreeMap;
public class MyComparatorTest {
public static void main(String[] args) {
Student[] students = {new Student(2, "student2", 20),
new Student(2, "student3", 30), new Student(4, "student4", 40)};
//这里如果只写students数组而不传入比较器的话会报错
//第二个参数是比较器类或者Lambda表达式
Arrays.sort(students, new AgeAscComparator());
Arrays.sort(students, (a, b) -> a.age - b.age);
for (Student student : students) {
System.out.println(student);
}
}
}
class AgeAscIdDescComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age == o2.age ? o2.id - o1.id : o1.age - o2.age;
}
}
class AgeAscComparator implements Comparator<Student> {
//这个是必须实现的方法,所有的比较器都需要遵循以下规律:
//1.返回负数的时候,认为第一个参数应该排在前面,例如数字类型的谁小谁在前
//2.返回正数的时候,认为第二个参数应该排在前面,例如数字类型的谁大谁在前
//3.返回0的时候,无所谓谁排在前面
@Override
public int compare(Student o1, Student o2) {
/**
* 这一句话也可以替换为:if(o1.age < o2.age) {
* return -1;
* } else if(o1.age > o2.age) {
* return 1;
* } else {
* return 0;
* }
*/
return o1.age - o2.age;
}
}
class Student {
int age;
String name;
int id;
public Student(int age, String name, int id) {
this.age = age;
this.name = name;
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", id=" + id +
'}';
}
}
运行结果:
Student{age=2, name='student2', id=20}
Student{age=2, name='student3', id=30}
Student{age=4, name='student4', id=40}
Process finished with exit code 0
这里我们看到其实age排序并不能明确区分student2还是student3在前
使用第二种方式写更复杂一点的比较器类(多个字段比较或者同一个字段相同的时候区别先后顺序)
class AgeAscIdDescComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
//如果age相同,按id降序
//如果age不同,按age升序
return o1.age == o2.age ? o2.id - o1.id : o1.age - o2.age;
}
}
传入这个比较器的时候运行结果如下(确定age相同的时候id大的在前):文章来源:https://www.toymoban.com/news/detail-424776.html
Student{age=2, name='student3', id=30}
Student{age=2, name='student2', id=20}
Student{age=4, name='student4', id=40}文章来源地址https://www.toymoban.com/news/detail-424776.html
到了这里,关于认识比较器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!