源碼研究:Java提供的排序算法sort是怎麼實現的?確定就是快排?

Java的JDK中我們見到的Collections.sort()和Arrays.sort()這兩個排序算法的實現方式是什麼,很多小夥伴心裡邊默認的應該是快排,但是不全對或者理解的不夠深刻,以下我們從源碼的層次一點點解釋一下這個問題:

源碼研究:Java提供的排序算法sort是怎麼實現的?確定就是快排?

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

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

源碼研究:Java提供的排序算法sort是怎麼實現的?確定就是快排?

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

源碼研究:Java提供的排序算法sort是怎麼實現的?確定就是快排?

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

那如果大於286呢,它就會判斷數組的連續升序和連續降序性好不好,如果好的話就用歸併排序,不好的話就用快速排序,看下面這段註釋就可以看出

源碼研究:Java提供的排序算法sort是怎麼實現的?確定就是快排?

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

源碼研究:Java提供的排序算法sort是怎麼實現的?確定就是快排?

即如果數組長度小於INSERTION_SORT_THRESHOLD(值為47)的話,那麼就會用插入排序了,不然再用雙軸快速排序!

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

源碼研究:Java提供的排序算法sort是怎麼實現的?確定就是快排?

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

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

源碼研究:Java提供的排序算法sort是怎麼實現的?確定就是快排?

會發現如果LegacyMergeSort.userRequested為true的話就會使用歸併排序,可以通過下面代碼設置為true:

源碼研究:Java提供的排序算法sort是怎麼實現的?確定就是快排?

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

源碼研究:Java提供的排序算法sort是怎麼實現的?確定就是快排?

如果不為true的話就會用一個叫TimSort的排序算法,這個算法有興趣的可以瞭解一下!

三、總結

在面試的時候如何秒殺眾人,當問到這個問題的時候,我們就不要再脫口而出只是快排而已了!



分享到:


相關文章: