一.Java比较器的概述
1.为什么要使用比较器?
Java 中的对象,正常情况下,只能进行 == 或 != 比较。不能使用 > 或 < 的比较,但是在开发场景中,我们需要对多个对象进行排序,这就需要比较对象的大小。此时我们如何实现呢?java为我们提供了两个接口,使用两个接口中的任何一个: Comparable 或 Comparator 即可实现对象的比较大小!
2.Java 实现对象排序的方式有两种:
2.1 自然排序:java. lang.Comparable 实现Comparable
接口的类必须实现compareTo(Object obj)
方法,两个对象即通过compareTo(Object obj)
方法的返回值来比较大小。
如果当前对象 this 大于形参对象 obj ,则返回正整数,如果当前对象 this 小于形参对象 obj ,则返回负整数,如果当前对象 this 等于形参对象 obj ,则返回零。
package comparer;
public class Person implements java.lang.Comparable {
private String name;
private char sex;
private int age;
public Person(String name, char sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
'}';
}
@Override
public int compareTo(Object o) {
//按照年龄大小从小到大排
if (o instanceof Person){
Person person= (Person) o;
if (this.age>person.age){
return 1;
}
if (this.age<person.age){
return -1;
}
if (this.age==person.age){
return 0;
}
}
throw new RuntimeException("传入的数据类型不一样");
}
}
package comparer;
import java.util.Arrays;
//自然排序
public class Comparable {
public static void main(String[] args) {
Person persons[]=new Person[4];
persons[0]=new Person("张三",'男',18);
persons[1]=new Person("李四",'男',19);
persons[2]=new Person("王二",'男',20);
persons[3]=new Person("小茹",'女',18);
Arrays.sort(persons);
for (Person person :persons
) {
System.out.println(person);
}
}
}
2.2 定制排序: java.util.Comparator,自然排序要求元素所属的类实现Comparable
接口,如果元素所属的类没有实现Comparable
接口,或不希望按照升序(默认情况)的方式排列元素或希望按照其它属性大小进行排序,则考虑使用定制排序。定制排序,通过Comparator
接口来实现。需要重写compare(T o1,T o2
)方法。
如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
package comparer;
public class Person {
private String name;
private char sex;
private int age;
public Person(String name, char sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
'}';
}
/*@Override
public int compareTo(Object o) {
//按照年龄大小从小到大排
if (o instanceof Person){
Person person= (Person) o;
if (this.age>person.age){
return 1;
}
if (this.age<person.age){
return -1;
}
if (this.age==person.age){
return 0;
}
}
throw new RuntimeException("传入的数据类型不一样");
}*/
}
package comparer;
import java.util.Arrays;
//定制排序
public class Comparator {
public static void main(String[] args) {
Person persons[]=new Person[4];
persons[0]=new Person("张三",'男',18);
persons[1]=new Person("李四",'男',19);
persons[2]=new Person("王二",'男',20);
persons[3]=new Person("小茹",'女',18);
Arrays.sort(persons, new java.util.Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
if (o1 instanceof Person && o2 instanceof Person){ //判断o1及o2是否为Person类型
Person person1=(Person) o1;
Person person2=(Person) o2;
return Integer.compare(person1.getAge(),person2.getAge());
}
throw new RuntimeException("传入的数据类型不一致!");
}
});
for (Person person :persons
) {
System.out.println(person);
}
}
}
3.Comparable 与 Comparator 的使用对比
Comparable 接口的方式一旦一定,保证 Comparable 接口实现类的对象在任何位置都可以比较大小 ,而 Comparator 接口属于临时性的比较。
再者一个很直观的是Comparable是在自定义类中将比较规则在类中写死了的,而Comparator则比较灵活,在比较时定义比较规则,
4.思考:如果同时用两种方式同时排序呢
4.1 先设置自然排序从大到小,定制排序从小到大。结果入下,结果从小到大,得出结论Comparator与Comparable同时存在的情况下,比较器Comparator优先级高。
5.总结
1.Comparable是java.lang包下的,Comparator是java.util包的;
2.Comparable接口使用时需要重写compareTo(T o)方法,实现Comparator接口必须重写compare(T o1,T o2)方法;
3.Comparable接口使用时需要修改实体类的代码,而Comparator接口使用时则不需要;
4.Comparator与Comparable同时存在的情况下,比较器Comparator优先级高。