今天在看相关代码时候看到了 Collections.sort(), 知道Collections是一个工具类 里面包含了很多排序查找等静态方法 是一个很好的util工具类。 但是代码没有仔仔细细的好好看看,今天看了一下 有点小体会。
首先,开始原始的方法:
public static <T> void sort(List<T> list, Comparator<? super T> c) {
Object[] a = list.toArray();
Arrays.sort(a, (Comparator)c);
ListIterator i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set(a[j]);
}
}
发现先将list变成Array,然后再排序,最后再转换回去。
先说toArray()方法吧
下面分别是ArrayList和LinkedList的实现
public Object[] toArray() {
return Arrays.copyOf(elementData, size); //elementData是真正存放东西的数组 size是这个list的长度
}//不难理解 ArrayList底层就是Array
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
for (Entry<E> e = header.next; e != header; e = e.next)
result[i++] = e.element;
return result;
}//也不难理解 无非就是便利一下 放到数组里并返回
看完了toArray() 再来看一下 sort()吧
Array.sort()是这样的
public static <T> void sort(T[] a, Comparator<? super T> c) {
T[] aux = (T[])a.clone();
if (c==null)
mergeSort(aux, a, 0, a.length, 0);
else
mergeSort(aux, a, 0, a.length, 0, c);
}
用的是mergeSort方法 这个方法的几个参数的含义是:src, dest, low, high, offset, compartor 见名之意
至于这个mergeSort方法嘛 肯定是一个递归操作了 但是这里面也有几个小细节
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 这里
// INSERTIONSORT_THRESHOLD是7
意思如果太小 用插入排序会更好
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
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) >>> 1; //注意 这里 没用'/2'
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++];
}
}
上面的一个方法 考虑到了差不多3种情况吧 真正的源码 果然严谨