简介:
在1.8以前的版本中对此方法进行了重写,若是还须要使用以前的排序算法,须要加上系统属性java.util.Arrays.useLegacyMergeSort=true,以前的排序使用优化后的归并排序,在1.8中使用TimSort算法来进行排序,TimSort算法是由Tim Peters在2002提出并首先实如今了phtyon中,是结合了合并排序(merge sort)和插入排序(insertion sort)的一种高效稳定的算法。算法原理看这里 https://blog.csdn.net/yangzhongblog/article/details/8184707java
Arrays.sort(Object[] a)分析
一、 方法声明算法
/** * 根据Comparable的天然排序将给定数组升序排序。全部元素必须实现Comparable 接口 * 并且,全部元素能相互比较,否则可能会抛出ClassCastException异常 * * 此排序确保是稳定的,若是两个元素e1.equals(e2),那么他们不会被再次排序 * * 该实现是一个稳定、自适应、重复的归并排序,当给定数组是局部排序的数组时它的时间复杂度比 nlogn更小, * 然而当给定数组是随机排序,它与传统的归并排序性能相同。若是给定数组大致有序,该算法只须要大概n次比较便可完成排序。 * * 该算法在输入数组为升序或降序时都能发挥优点,而且在该数组部分有序的状况下也能发挥其优点, * 它能经过简单链接便可很好的完成将多个数组进行合并 */ public static void sort(Object[] a) { //若是要兼容1.8以前的排序程序,在系统属性中须要添加属性,如:java -jar -Djava.Arrays.uselegacyMergeSort=true xx.jar if (LegacyMergeSort.userRequested) legacyMergeSort(a); else //真正的TimSort算法实如今ComparableTimSort中 ComparableTimSort.sort(a, 0, a.length, null, 0, 0); }
二、 ComparableTimSort.sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen)分析数组
/** * 将数组指定范围内的元素排序 * * [@param](https://my.oschina.net/u/2303379) a 被排序数组 * [@param](https://my.oschina.net/u/2303379) lo 排序开始元素index * [@param](https://my.oschina.net/u/2303379) hi 排序结束元素index,不包含此index * [@param](https://my.oschina.net/u/2303379) work a workspace array (slice) * [@param](https://my.oschina.net/u/2303379) workBase origin of usable space in work array * @param workLen usable size of work array * @since 1.8 */ static void sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen) { //保证数组的合法性 assert a != null && lo >= 0 && lo <= hi && hi <= a.length; int nRemaining = hi - lo; //对于只有0|1个元素的数组,不须要进行排序 if (nRemaining < 2) return; // Arrays of size 0 and 1 are always sorted // If array is small, do a "mini-TimSort" with no merges //若是数组比较小,直接使用二叉插入排序进行排序 if (nRemaining < MIN_MERGE) { //计算数组头部递增或递减的的序列长度,若是是递减,则翻转,保持升序 int initRunLen = countRunAndMakeAscending(a, lo, hi); //使用二叉插入排序对在initRunLen后的元素进行排序 binarySort(a, lo, hi, lo + initRunLen); return; } /** * March over the array once, left to right, finding natural runs, * extending short natural runs to minRun elements, and merging runs * to maintain stack invariant. */ //构造ComparableTimSort对象 ComparableTimSort ts = new ComparableTimSort(a, work, workBase, workLen); //计算最小run的长度 int minRun = minRunLength(nRemaining); do { // Identify next run //计算当前排序的run的长度,若是为递减数组则翻转 int runLen = countRunAndMakeAscending(a, lo, hi); // If run is short, extend to min(minRun, nRemaining) //若是当前run的长度小于minRun,则进行扩展,在扩展过程当中使用二叉排序来排序扩展的的元素 if (runLen < minRun) { int force = nRemaining <= minRun ? nRemaining : minRun; binarySort(a, lo, lo + force, lo + runLen); runLen = force; } // Push run onto pending-run stack, and maybe merge //将此run放入栈中 ts.pushRun(lo, runLen); //执行合并逻辑,合并的时候也作了一些优化 ts.mergeCollapse(); // Advance to find next run lo += runLen; nRemaining -= runLen; } while (nRemaining != 0); // Merge all remaining runs to complete sort assert lo == hi; //保证最后的run都被合并 ts.mergeForceCollapse(); assert ts.stackSize == 1; }