内容学习于:edu.aliyun.com
1. 比较器问题引出
所谓的比较器指的就是进行大小关系的确定判断,下面首先来分析一下比较器存在的意义。
如果要进行数组操作,肯定使用java.util.Arrays的操作类完成,这个类里面提供有绝大部分的数组操作支持,同时在这个类里面还提供有一种对象数组的排序支持: public static void sort(Object[] a);
对象数组排序代码:
public class JavaAPIDemo {
public static void main(String[] args) {
Integer data[] = new Integer[]{10, 9, 5, 2, 20};//对象数组
Arrays.sort(data);//进行对象数组排序
System.out.println(Arrays.toString(data));
}
}
结果:
[2, 5, 9, 10, 20]
字符数组排序:
public class JavaAPIDemo {
public static void main(String[] args) {
String data[] = new String[]{"X", "K", "O", "P", "C"};//对象数组
Arrays.sort(data);//进行对象数组排序
System.out.println(Arrays.toString(data));
}
}
结果:
[C, K, O, P, X]
代码:
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}' + "\n";
}
//无参构造、setter、getter省略
}
public class JavaAPIDemo {
public static void main(String[] args) {
Person[] data = new Person[]{
new Person("小明-A", 100),
new Person("小明-B", 80),
new Person("小明-C", 90)
};//对象数组
Arrays.sort(data);//进行对象数组排序
System.out.println(Arrays.toString(data));
}
}
结果:
Exception in thread “main” java.lang.ClassCastException: class com.xzzz.e20200114_chapter1.Person cannot be cast to class java.lang.Comparable
<mark>任意的一个类默认情况下是无法使用系统内部的类实现数组排序或比较需求的</mark>,是因为没有明确的指定出到底该如何进行比较的定义(没有比较规则),那么这个时候在Java里面为了统一比较规则的定义,所以提供有比较器的接口: Comparable 接口
2. Comparable比较器
通过分析可以发现如果要实现对象的比较肯定需要有比较器来制定比较规则,而比较的规则就通过Comparable来实现,对于Comparable而言,需要清楚其基本的定义结构:
定义:
public interface Comparable<T>{
/** * 实现对象的比较处理操作 * @param o 要比较的对象 * @return 当前数据比传入的对象小返回负数,如果大于返回正数,如果等于返回0 */
public int compareTo(T o);
}
如下图所示:
实现自定义比较操作:
class Person implements Comparable<Person> {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}' + "\n";
}
@Override
public int compareTo(Person per) {
return this.age - per.age;
}
//无参构造、setter、getter省略
}
public class JavaAPIDemo {
public static void main(String[] args) {
Person[] data = new Person[]{
new Person("小明-A", 100),
new Person("小明-B", 80),
new Person("小明-C", 90)
};//对象数组
Arrays.sort(data);//进行对象数组排序
System.out.println(Arrays.toString(data));
}
结果:
[Person{name=‘小明-B’, age=80}
, Person{name=‘小明-C’, age=90}
, Person{name=‘小明-A’, age=100}
]
排序里面只需要有一个compareTo()方法进行排序规则的定义,而后整个Java系统里面就可以为其实现排序处理了。
3. Comparator比较器(定义了函数式接口)
Comparator属于一种挽救的比较器支持,其主要的目的是解决一些没有使用Comparable排序的类的对象数组排序。
比较方法:int compare(T o1,T o2)
后来经过了若干版本的迭代更新之后发现需要对Person类进行排序处理,但是又不能够去修改Person类(无法实现Comparable接口),所以这个时候就需要采用一种挽救的形式来实现比较,在Arrays类里面排序有另外一种实现:
基于Comparator的排序处理: public static void sort(T[] a, Comparator<? super T>c)
如下图所示:
在java.util.Comparator里面最初只定义有一个排序的compare(方法(public int compare(T o1, T o2)),但是后来持续发展又出现了许多的static方法。
实现排序代码:
class PersonComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}' + "\n";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class JavaAPIDemo {
public static void main(String[] args) {
Person[] data = new Person[]{
new Person("小明-A", 100),
new Person("小明-B", 80),
new Person("小明-C", 90)
};//对象数组
Arrays.sort(data, new PersonComparator());//进行对象数组排序
System.out.println(Arrays.toString(data));
}
}
结果:
[Person{name=‘小明-B’, age=80}
, Person{name=‘小明-C’, age=90}
, Person{name=‘小明-A’, age=100}
]
<mark>对于这种排序的操作如果不是必须的情况下强烈不建议使用Comparator,最好以Comparable为主。</mark>
<mark>面试题:请解释Comparable与Comparator的区别?</mark>
java.lang.Comparable是在类定义的时候实现的父接口,主要用于定义排序规则,里面只有一个compareTo()方法;
java.util.Comparator 是挽救的比较器操作,需要设置单独的比较器规则类实现排序,里面有compare()方法。