当排序基本数据类型和非自定义的引用类型时,我们通常会调用Arrays.sort(Object o)
方法进行比较,实际上,引用类型(String、Integer等)能够调用上述方法,是因为该类已经实现了Comparable接口中的compareTo()方法,所以可以非常方便的比较。下面是Integer包装类实现Comparable接口中compareTo方法的源代码:
public int compareTo(Integer anotherInteger) {
int thisVal = this.value;
int anotherVal = anotherInteger.value;
return (thisVal1 : (thisVal==anotherVal ? 0 : 1));
}
但是当我们想要比较自己定义的引用类型时,该怎么办呢?比如想要让Employee类的集合对象List
按照工资的高低排序,能够直接调用Arrays.sort(es)
吗?答案当然是:NO!
让一个类使用排序服务必须让它实现Comparable类的compareTo方法。因为要向sort方法提供对象的比较方式。但是为什么不能在Employee类直接提供一个compareTo方法,而必须实现Comparable接口呢?
理由:java程序设计语言是一种强类型语言。在调用方法的时候,编译器将会检查这个方法是否存在。在sort方法中有这样的语句
// Insertion sort on smallest arrays
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; ifor (int j=i; j>low && ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
swap(dest, j, j-1);
return;
}
因此编译器必须确认dest[j-1]有compareTo方法。如果dest是一个Comparable对象的数组,就可以确保拥有compareTo方法,因为每一个实现comparable接口的类必须提供这个方法的实现方式。
package comparable;
public class People2 implements Comparable{
private String name;
private double salary;
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public People2(String name, double salary) {
super();
this.name = name;
this.salary = salary;
}
public void setName(String name) {
this.name = name;
}
public People2(String name) {
super();
this.name = name;
}
@Override
public String toString() {
return "People2 [name=" + name + " salary=" + salary + "]";
}
@Override
public int compareTo(People2 o) {
// TODO Auto-generated method stub
return Double.compare(this.salary, o.salary);
}
}
package comparable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class People2Test {
public static void main(String[] args){
List p = new ArrayList();
People2 p1 = new People2("a",1);
People2 p2 = new People2("bbb",2222);
People2 p3 = new People2("bbbss",333);
p.add(p1);
p.add(p2);
p.add(p3);
//Collections类的sort方法可以进行排序,List类型的只能使用该类的排序方法,不可以使用Arrays类的sort
Collections.sort(p);
for(People2 cur: p)
System.out.println(cur);
}
}
对一个对象数组进行排序,就可以应用上述方法来实现。但是如果想要改变已有的排序方法,如想要更改String类的的compareTo方法的功能。现有的String.compareTo方法是可以按照字典的顺序比较字符串。但是如果想要按照字符串长度递增的顺序排序字符串该怎么办呢?
下面显示Comparator接口的源码:
public interface Comparator {
int compare(T o1, T o2);
boolean equals(Object obj);
}
想要哪找长度比较字符串,可以定义一个实现Comparator接口的compare类
public class LengthComparator implements Comparator<String>{
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
return o1.length() - o2.length();
}
public static void main(String[] args){
Comparator p = new LengthComparator();
String[] s = {"fujie","cuidapanger","xiaocui"};
String[] ss = {"fujie","cuidapanger","xiaocui"};
Arrays.sort(s);
//输出结果
//cuidapanger
//fujie
//xiaocui
for(String cur: s){
System.out.println(cur);
}
//第一个参数是:要排序的对象;第二个参数:是实现Comparator接口的类的实例,通过它调用更改后的compare方法
Arrays.sort(ss, p);
//输出结果
//fujie
//xiaocui
//cuidapanger
for(String cur: ss){
System.out.println(cur);
}
}
}
一个类实现Comparable接口就表明这个类的对象之间是可以进行相互比较的,这个类对象组成的集合就可以调用Collections类的sort方法进行比较
情况一:实体类本身没有实现Comparable方法,但是又希望比较类对象,那这个时候就可以使用Comparator接口,通过实现该接口的compare方法来实现排序功能。简言之:实体类还是实体类,排序交给比较器Comparator实现类
情况二:想要String类不仅可以按照字典顺序排序,还可以按照字符串长度排序时就可以用比较器Comparator。情况见上述代码。因此可以使用比较器为一个类提供多种比较的方式