本文主要介绍了Collections.sort方法在JDK1.6中的源码实现(JDK版本1.6.0_45)html
1.Collections.sort()算法
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转换为数组并调用了Arrays.sort()方法(至于这个Comparator是一种比较器,外界须要实现其compare方法;还有一种是Comparable,实现的是compareTo方法,有兴趣的能够研究一下。),在对数组进行排序以后,经过迭代器将排序结果更新到list中。(迭代器的相关知识不作介绍了,由于我也没看这部分的源码)数组
2.Arrays.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); }
先是利用Object的clone方法建立了一个a的副本对象(Object的clone方法为浅克隆方式,它只克隆了自身对象和对象内部实例变量的地址引用。也就是说在堆内存只是建立了a自身副本对象,而在栈内存中建立了对象内部实例变量的地址引用副本。)spa
判断比较器c存不存在,实际上mergeSort(aux, a, 0, a.length, 0)和mergeSort(aux, a, 0, a.length, 0, c)内部实现方式同样,只是若是比较器c(Comparator)不存在,mergeSort(aux, a, 0, a.length, 0)内部会使用Comparable比较器的compareTo方法。.net
3.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 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; 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++]; } }
这一部分代码比较多,首先程序会经过判断length < INSERTIONSORT_THRESHOLD(INSERTIONSORT_THRESHOLD默认为7),若是数组长度小于7,会使用直接插入排序算法。code
这个上张图解释一下,图片来源http://www.javashuo.com/article/p-mnytybcp-hm.html。htm
如今来看一下代码,代码很简单,两个循环,外层循环遍历数组(图中的待排序序列),内层循环将每一次待排序的值按顺序放入有序序列中(只是一种表达方式,实际上就是交换),好比图中在对1进行插入时,会先跟前一个元素9进行比较,1<9,交换位置,而后1再跟前一个元素3比较,1<3,交换位置。对象
要是数组长度不小于7呢,就会使用归并排序算法啦,有关归并排序算法的介绍能够参考这篇博客http://www.javashuo.com/article/p-nkdsmljg-cd.html,这里就不贴图了。
归并排序的核心思想呢就是分而治之嘛,提及来挺容易的哈!
下面代码经过采用递归方式实现分的思想,分到最后仍是用了直接插入排序,这个有个地方须要注意一下,就是src和dest的参数位置(数组的起止位置就不用说了吧!),在调用递归时,是将src数组做为排序对象进行排序的,而后dest数组是依据src进行排序(下边代码具体说)。
int destLow = low; int destHigh = high; low += off; high += off; int mid = (low + high) >>> 1; mergeSort(dest, src, low, mid, -off, c); mergeSort(dest, src, mid, high, -off, c);
如今分完了,怎么治呢?前面所说的dest数组是依据src进行排序在此进行了体现,最开始说的两个mergeSort方法的不一样之处(比较器)在这也能看出。
首先有一种特别友好的状况,那就是分完的前半部分最大的那个正好小于等于后半部分最小的元素(这只是递归过程当中的一个分支),那么皆大欢喜,src数组已是有序的了,只需将src数组复制到目标数组中(System.arraycopy具体用法自行上网查吧)。
// 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++]; }
其余状况怎么处理呢,这个再贴张图,图片来源https://blog.csdn.net/ghsau/article/details/42060651,这篇博客是我参考的博客,你们也能够看看。
思想很简单,循环整个数组,比较左边的元素和右边的元素,谁小把谁放到dest中(再次重申,这只是递归过程当中的一个分支),而后移动对应指针,直到src全部元素都放入到dest中。
例如一开始是2和1进行比较,1小放入dest中,p不变,q指向5(看作指针),i指向下一个位置;2和5比较,2小放入dest中,p指向3,q不变,i指向下一个位置,以此类推,直到循环结束。
到这里算是写完了,写的可能很差,刚毕业大学生水平有限,工做以后的第一篇博客,请原谅我一些地方的无知;若是有什么错误,请必定要指出,万分感谢,您的意见是我成长的催化剂。
下面整理一下参考资料。
https://blog.csdn.net/ghsau/article/details/42060651
https://www.jianshu.com/p/1efc3aa1507b
http://www.javashuo.com/article/p-mnytybcp-hm.html
http://www.javashuo.com/article/p-nkdsmljg-cd.html
后面若是有机会,会写一篇jdk1.7以后有关sort这一部分的博客。
疑问:mergeSort中有一个off参数,我的理解是限制排序集合的区域范围(起止怎么肯定的。。。)?JDK1.7中sort方法中的paramInt1和paramInt2是否是起到了相似的功能?