Comparator源码解析
在对数组以及集合的排序中,我们经常使用Arrays.sort(A);或者Collections.sort(A)对数组或集合进行排序。当我们需要自定义排序规则的时候,就要使用Comparable或者Comparator接口。Comparable是和具体的类进行绑定,也就是“静态绑定”。而Comparator是在具体的类中可以选择不同的Comparator进行绑定,也就是“动态绑定”(策略模式)。关于两者的使用都比较简单,主要是重写compare()方法。这里只分析Comparator在排序中的应用。
在使用Comparator时,首先是重写其中的compare()方法,如下,有三个返回值。
Comparator compare = new Comparator<Point2>(){
//c.compare(points[i-1],points[i])
@Override
public int compare(Point2 o1, Point2 o2) {
if(o1.value > o2.value) {
return 1;
}else{
return -1;
}
}};
源码中对三个返回值是这样子定义的
Compares its two arguments for order. Returns a negative integer,zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
即返回-1,0,1对应01小于、等于、大于02。
然后就是在代码中使用了
Arrays.sort(p2,compare);
在Arrays.sort(p2,compare);中代用了这段代码 mergeSort(aux, a, 0, a.length, 0, c); 我们进入到这段代码中,这段代码就是排序的核心。
private static void mergeSort(Object[] src,
Object[] dest,
int low, int high, int off,
Comparator c) {
int length = high - low;
// Insertion sort on smallest arrays
//当数组的长度小于某个阈值(这里官方定义是7)使用冒泡排序法
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
//这里就调用到我们定义的排序规则,即当dest[j-1]>dest[j]时,
//交换两个元素的顺序
for (int j=i; j>low && c.compare(dest[j-1], 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)/2;
//在代码中为了避免溢出常写成int mid = low + (high - low)/2,
//这里使用位移运算符是因为在计算机中,位移运算要以除法运算快。
int mid = (low + high) >>> 1;
mergeSort(dest, src, low, mid, -off, c);
mergeSort(dest, src, mid, high, -off, c);
// 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 (c.compare(src[mid-1], 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 && c.compare(src[p], src[q]) <= 0)
dest[i] = src[p++];
else
dest[i] = src[q++];
}
}