Collections.sort in JDK6:MergeSort
来源:互联网 发布:python 3.0 廖雪峰 编辑:程序博客网 时间:2024/04/29 19:39
本文是对JDK6中Collections.sort方法的源码解析,也可以看作是对Comparison method violates its general contract!的后续分析。在JDK6中,该方法底层使用的是经过优化后的归并排序,废话不多说,直接看源码。
初始状态:
循环一次后:
每次都比较src[p]和src[q],将较小的元素存储到dest[i],不断的循环比较,直至整个数组都有序。
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方法排序,最后将排好顺序的值覆盖到原list上。
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);elsemergeSort(aux, a, 0, a.length, 0, c);}克隆一个数组,如果比较器为空,mergeSort(aux, a, 0, a.length, 0);如果比较器不为空,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 arraysif (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 srcint 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 destfor(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++];elsedest[i] = src[q++];}}我们分段来看。
int length = high - low;// Insertion sort on smallest arraysif (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;}这里有一个常量INSERTIONSORT_THRESHOLD。
/** * Tuning parameter: list size at or below which insertion sort will be * used in preference to mergesort or quicksort. */private static final int INSERTIONSORT_THRESHOLD = 7;当数组长度<7时,这里使用了直接插入排序。直接插入排序的过程可以看这个视频,插入排序适用于小数列的排序。这里是JDK6中归并排序的第一个优化。
// Recursively sort halves of dest into srcint destLow = low;int destHigh = high;low += off;high += off;int mid = (low + high) >>> 1;// 中间索引,相当于(low + high) / 2mergeSort(dest, src, low, mid, -off, c);// 排序左边mergeSort(dest, src, mid, high, -off, c);// 排序右边这里开始递归排序,我们不需要关注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 (c.compare(src[mid-1], src[mid]) <= 0) { System.arraycopy(src, low, dest, destLow, length); return;}左边和右边排好序之后,开始合并。这时src[low ~ mid - 1]和src[mid ~ high - 1]都是有序的,这时比较src[mid - 1]和src[mid],如果前者比后者小,那么皆大欢喜,真个src数组就是有序的了,只需将其复制到目标数组后,就完成了排序,不过这种碰运气的几率会比较小。这里是JDK6中归并排序的第二个优化。
// Merge sorted halves (now in src) into destfor(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++];elsedest[i] = src[q++];}程序执行到这里,进行传统的合并操作。其过程如下图:
初始状态:
循环一次后:
每次都比较src[p]和src[q],将较小的元素存储到dest[i],不断的循环比较,直至整个数组都有序。
最终:
JDK6中的排序是基于传统的归并排序做了部分优化,这两个优化都很简单,实际上效率并未提高多少。所以在JDK7中将其替换为TimSort,下回分解。
(完)
本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/42060651,转载请注明。
2 0
- Collections.sort in JDK6:MergeSort
- 深入jdk——追踪Collections.sort 引发的bug(1)mergeSort
- Using Collections.sort and Comparator in Java
- Using Collections.sort and Comparator in Java
- MergeSort and Quick Sort
- Collections.sort
- Collections sort
- Collections.sort
- Collections-sort
- Collections.sort
- Collections.sort
- Mergesort in Java
- mergesort in python
- Arrays.sort()、Collections.sort()
- 集合(Collections-sort)-(Collections-max)-(Collections-binarySearch)
- Collections.sort();和Arrays.sort()
- insertion mergesort bubble sort 复习 python
- Collections.sort()排序使用方法
- Google Protobuf 协议分析
- 结构数组,结构数组类型(typedef)
- github命令大全
- OC中的NSArray
- aix 命令:lsdev、lsattr、lscfg
- Collections.sort in JDK6:MergeSort
- CentOS7部署php+apache+oracle
- 第17周项目1-体会函数参数传递
- WCF-事务
- 第14章-重载运算符与类型转换
- 结构型模式之Adapter模式
- 第十七周 项目5 处理时间日期(计算这是第几天或第几秒的问题)
- 设计模式之六大原则
- (5)rosservice与rosparam