一.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优先级高。