主要介绍Comparable接口
我们在对数据类型进行判断时可以用>,<,=之类的符号比较大小
通常我们可能需要对某个类里的某一属性进行比较,然后对这个对象进行排序,比方一个employee类,有两个属性name,salary
假如对根据salary大小进行比较
@Data
public class Employee implements Comparable<Employee> {
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
@Override
public int compareTo(Employee other) {
return Double.compare(salary, other.salary);
}
public static void main(String[] args) {
Employee[] staff = new Employee[3];
staff[0] = new Employee("Sun Wukong", 130000);
staff[1] = new Employee("Pig Bajie", 11000);
staff[2] = new Employee("Sha Wujing", 12000);
Arrays.sort(staff);
for(Employee employee:staff){
System.out.println(employee.name+"::"+employee.salary);
}
}
}
输出
Pig Bajie::11000.0
Sha Wujing::12000.0
Sun Wukong::130000.0
以name的长度比较
@Data
public class Employee implements Comparable<Employee> {
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
@Override
public int compareTo(Employee other) {
return name.length()-other.name.length();
}
public static void main(String[] args) {
Employee[] staff = new Employee[3];
staff[0] = new Employee("Sun Wukong", 130000);
staff[1] = new Employee("Pig Bajie", 11000);
staff[2] = new Employee("Sha Wujing", 12000);
Arrays.sort(staff);
for(Employee employee:staff){
System.out.println(employee.name+"::"+employee.salary);
}
}
}
输出
Pig Bajie::11000.0
Sun Wukong::130000.0
Sha Wujing::12000.0
这里可能会有疑惑:在main方法里似乎没有调用Comparable接口的compareTo方法,那门compareTo哪里执行的
而且如果Employee 不implements Comparable会执行报错:
Exception in thread "main" java.lang.ClassCastException: com.wangzhou.datastructure.comparator.Employee cannot be cast to java.lang.Comparable
这里请看Arrays.sort(staff);的源码
public static void sort(Object[] a) {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a);
else
ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
}
再看legacyMergeSort(a);
private static void legacyMergeSort(Object[] a) {
Object[] aux = a.clone();
mergeSort(aux, a, 0, a.length, 0);
}
再看mergeSort(aux, a, 0, a.length, 0);
private static void mergeSort(Object[] src,
Object[] dest,
int low,
int high,
int off) {
int length = high - low;
// Insertion sort on smallest arrays
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
for (int j=i; j>low &&
((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
swap(dest, j, j-1);
return;
}
// Recursively sort halves of dest into src
int destLow = low;
int destHigh = high;
low += off;
high += off;
int mid = (low + high) >>> 1;
mergeSort(dest, src, low, mid, -off);
mergeSort(dest, src, mid, high, -off);
// If list is already sorted, just copy from src to dest. This is an
// optimization that results in faster sorts for nearly ordered lists.
if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
System.arraycopy(src, low, dest, destLow, length);
return;
}
// Merge sorted halves (now in src) into dest
for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
dest[i] = src[p++];
else
dest[i] = src[q++];
}
}
在mergeSort这个方法里的这句
if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
System.arraycopy(src, low, dest, destLow, length);
return;
}
这里的src实际就是我们的Employee类,这里会对Employee里的compareTo调用,进行比较
比方说这个if判断里需要<=0的情况,其实就是name.length()<=other.name.length()
这并不代表比较的这个过程,只是说明compareTo是怎么被调用的,具体的比较过程请详细阅读源码