JDK提供的排序算法是怎麼實現的?

前幾天整理的一套面試題,其中有一個問題就是Java的JDK中咱們見到的Collections.sort()和Arrays.sort()這兩個排序算法的實現方式是什麼,不少小夥伴內心邊默認的應該是快排,可是不全對或者理解的不夠深入,如下咱們從源碼的層次一點點解釋一下這個問題:面試

1、Arrays.sort()的排序算法

先來看看Arrays.sort(),sort方法擁有不少的重載,有十幾種,以int查看以下:算法

public static void sort(int[] a) {
    DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}

能夠看到這裏有一個DualPivotQuicksort,DualPivotQuicksort翻譯過來就是雙軸快速排序(關於雙軸快速排序咱們後期在討論,能夠認爲是對咱們普通使用的快排的一種改進,另外還有一種改進是三路快排!),再次點進去,能夠發現有這麼一段代碼:數組

if (right - left < QUICKSORT_THRESHOLD) {
    sort(a, left, right, true);
    return;
}

發現若是數組的長度小於QUICKSORT_THRESHOLD的話就會使用這個雙軸快速排序,而這個值是286。ui

那若是大於286呢,它就會判斷數組的連續升序和連續降序性好很差,若是好的話就用歸併排序,很差的話就用快速排序,看下面這段註釋就能夠看出:spa

/*
  * The array is not highly structured,
  * use Quicksort instead of merge sort.
  */

那如今再回到上面的決定用雙軸快速排序的方法上,再點進去,發現又會多一條判斷:翻譯

// Use insertion sort on tiny arrays
if (length < INSERTION_SORT_THRESHOLD) {
    //。。。。
}

即若是數組長度小於INSERTION_SORT_THRESHOLD(值爲47)的話,那麼就會用插入排序了,否則再用雙軸快速排序!code

總結,若是數組長度大於等於286且連續性好的話,就用歸併排序,若是大於等於286且連續性很差的話就用雙軸快速排序。若是長度小於286且大於等於47的話就用雙軸快速排序,若是長度小於47的話就用插入排序。示意圖以下: 
blog

2、Collections.sort()的排序算法

再來看看Collections.sort(),一步步點進去,發現會進到Arrays裏: 

會發現若是LegacyMergeSort.userRequested爲true的話就會使用歸併排序,能夠經過下面代碼設置爲true: 

不過方法legacyMergeSort的註釋上有這麼一句話,說明之後傳統歸併可能會被移除了。 

若是不爲true的話就會用一個叫TimSort的排序算法,這個算法有興趣的能夠了解一下!排序

相關文章
相關標籤/搜索