Java中Collections與Arrays的排序解析
排序是所有變成語言中都會有的部分,常見的排序方式有冒泡、快速、插入三種,那麼Java語言本身使用的排序方式是哪種呢?
下面我們就來研究下Java原始碼內集合(List)以及陣列(Array)的排序方式。
首先從Collections的排序方法說起,Collections對List型別的排序方法sort有兩種,一種是使用Java內部的排序規則(自然排序,根據ASCII碼的大小),另一種是使用使用者自定義的實現Comparator介面的排序類來定義排序規則。
開啟Collections工具類的原始碼: sort(List,Comparator)方法: 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]); } } sort(List)方法: public static <T extends Comparable<? super T>> void sort(List<T> list) { Object[] a = list.toArray(); Arrays.sort(a); ListIterator<T> i = list.listIterator(); for (int j=0; j<a.length; j++) { i.next(); i.set((T)a[j]); } }
我們發現Collections中的兩個sort方法驚人的相似,都是先將要排序的List轉化為陣列,然後呼叫Arrays類中相應的sort方法排序,再然後得到List物件的迭代器,最後迭代List並將排序後的陣列按序賦值到List中。
綜上,我們可以得知Collections中的排序方式落實在Arrays類。
接下來,檢視Arrays類中的sort類,程式碼就不貼出了,自己檢視即可,最後的排序實現類是Arrays類中的mergeSort(原陣列,目標陣列,目標陣列起始位置,目標陣列的長度,偏移量)。
最最後,排序的實現重點在Arrays類中的mergeSort方法,上程式碼註釋:
/** * @Title: Java中List與Array的核心排序方法 * @param @param src 原陣列 * @param @param dest 目標陣列,這裡的目標陣列是原陣列的clone * @param @param low 目標陣列中排序存放開始的索引 * @param @param high 目標陣列中排序存放結束的索引 * @param @param off 原陣列中生成對應的偏移量 * @return void * @throws */ private static void mergeSort(Object[] src, Object[] dest, int low, int high, int off) { //得到目標陣列存放排序結果的長度 int length = high - low; //使用插入排序方式對目標陣列中存放排序結果的部分排序 if (length < INSERTIONSORT_THRESHOLD) { for (int i = low; i < high; i++) for (int j = i; j > low && ((Comparable) dest[j - 1]).compareTo(dest[j]) > 0; j--) swap(dest, j, j - 1); return; } //利用遞迴,不斷的二分陣列,直到陣列的長度小於INSERTIONSORT_THRESHOLD(預設為7)則使用插入排序排序 int destLow = low; int destHigh = high; low += off; high += off; //利用無符號右移的方式得到中間位置的索引 int mid = (low + high) >>> 1; //由於dest陣列是src陣列的clone,所以無論幾遍的dest與src交換都能保證排序的部分不重複 mergeSort(dest, src, low, mid, -off); mergeSort(dest, src, mid, high, -off); //如果說二分後的兩個部分恰好前部分都小於後部分,那麼只需要將原陣列中的資料從low起始的部分拷貝到desc中destLow起始的部分,拷貝長度為length if (((Comparable) src[mid - 1]).compareTo(src[mid]) <= 0) { //這裡呼叫了native方法,高效、快速 System.arraycopy(src, low, dest, destLow, length); return; } //將兩個排好序的部分合成到一起 //這裡就是將陣列中分開的兩部分,從兩部分的起始位置也就是索引為0和中間值的兩個值比較大小後,依次填充到目標陣列中 //每次填充一個值,兩部分填充過的部分索引+1,直到完全合併 for (int i = destLow, p = low, q = mid; i < destHigh; i++) { if (q >= high || p < mid && ((Comparable) src[p]).compareTo(src[q]) <= 0) dest[i] = src[p++]; else dest[i] = src[q++]; } }
對於實現Comparator介面,即使用者自定義排序規則的方式,就是簡單的將以上方法中插入排序部分中的使用預設的Comparable部分使用使用者定義的排序規則來排序。
通過以上分析以及對程式碼的檢視,我們瞭解到Java內部的排序是對大陣列使用合併排序進行遞迴分解,直到分解為目標長度的小陣列為止,然後小陣列內部使用插入排序進行排序,最後還是合併排序進行合併。
相關推薦
Java中Collections與Arrays的排序解析
排序是所有變成語言中都會有的部分,常見的排序方式有冒泡、快速、插入三種,那麼Java語言本身使用的排序方式是哪種呢? 下面我們就來研究下Java原始碼內集合(List)以及陣列(Array)的排序方式。 首先從Collections的排序方法說起,Collections對L
java中Collections.sort排序詳解
比較器 元素 .net 字符 atp style pri com 實現接口 Comparator是個接口,可重寫compare()及equals()這兩個方法,用於比價功能;如果是null的話,就是使用元素的默認順序,如a,b,c,d,e,f,g,就是a,b,c,d,e,f
java中Collection,Arrays內元素的排序問題(comparable,comparator接口的應用)
區別 ons err adt 分享圖片 ima http 排序 list 在我們通常對於collection的使用過程中,很多時候都需要對內部的元素進行排序。對於這個排序,通常可以有兩種實現方式: 1.創建一個comparator類實現comparator接口,然後應用co
黑馬程式設計師——Java集合框架(三)之Map集合、Collections與Arrays工具類
-----------android培訓、java培訓、java學習型技術部落格、期待與您交流!------------ Map集合 一、概述 Map集合儲存的元素是鍵值對,即將鍵和值一對一對往裡存,而且要保證鍵的唯一性。 問題思考: 1.如何保證鍵的唯一性?
java中 collection 與 collections 的區別
今天面試時,筆試題遇到這個問題,從網上查了些資料,總結如下: 1、java.util.Collection 是一個集合介面。它提供了對集合物件進行基本操作的通用介面方法。Collection介面在Java 類庫中有很多具體的實現。 Collection介面的
Java中Collections.sort()排序詳解
你也可以檢視我的其他同類文章,也會讓你有一定的收貨 第一種:Comparable 排序介面 若一個類實現了Comparable介面,就意味著“該類支援排序”。 假設“有一個List列表(或陣列),裡面的元素是實現了Comparable介面的類”,則
JAVA 集合類(Collection)、List、Set、Map、Collections與Arrays、泛型
1. 集合堆疊、佇列資料結構的特點1.1. 什麼是集合儲存物件的容器,面嚮物件語言對事物的體現都是以物件的形式,所以為了方便對多個物件的操作,儲存物件,集合是儲存物件最常用的一種方式。集合的出現就是為了持有物件。集合中可以儲存任意型別的物件, 而且長度可變。在程式中有可能無法
轉:Java中String與byte[]的轉換
輸出字符串 單個字符 linu 編輯 繁體 中國人 對象 本質 計算機基礎知識 String s = "fs123fdsa";//String變量 byte b[] = s.getBytes();//String轉換為byte[] String t = new Stri
Java中的訪問權限解析
logs java語言 mil style 解析 sta 重要 技術分享 [] 在Java中不同的對象和類擁有不同的訪問權限,所以在java中對不同的類和對象進行權限的設置顯得尤為重要. java中的權限主要分為四種,public,protect,private,和defa
201671010145 2016-2017-3《Java程序設計》Java中類與對象的區別
import -c indent cin ria wid let isp ans 1.什麽是類呢? 書面語句:類是一種事物,或者一類相同物體的抽象.類是對一個或者幾個相似對象的描述,它把不同對象具有的共性抽象出來.也可以說類是同一類對象的原型. 例如:人就是一個類,因為它是
java中日期與字符串之間的轉換
oda ava ret .text tostring simple cep 日期格式 clas import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;
Java中Date與String的相互轉換
獲取 org 復制 日期類型 junit clas 時間 -m see 我們在註冊網站的時候,往往需要填寫個人信息,如姓名,年齡,出生日期等,在頁面上的出生日期的值傳遞到後臺的時候是一個字符串,而我們存入數據庫的時候確需要一個日期類型,反過來,在頁面上顯示的時候,需要從數據
Java發展前景與職業方向解析
請求 引擎 解釋器 詹姆斯 千萬 正常的 工程 沒有 特性 大多數人選擇Java可能只是因為聽說Java前景好、Java比較好找工作、Java語言在TIOBE排行榜上一直位於前三等等之類的原因,但是Java具體好在哪裏,心裏卻是沒有什麽概念的。本文為你解答學Java的前景。
java 中string與bytes的轉換總結
set post java lan bsp nbsp 發現 blog fff 最近在和導航設備的通訊服務,和設備通訊時,需要將字符串以UTF-16編碼傳遞。 那如何將string,轉換為byte[]?其實Java提供了現成的實現:java.lang.string.getby
讓你徹底明白JAVA中堆與棧的區別
java程序 運行 一點 動態 自動變 key 空間 類型 lin 原文地址:http://www.2cto.com/kf/201302/190704.html 簡單的說: Java把內存劃分成兩種:一種是棧內存,一種是堆內存。 在函數中定義的一些基本類型的變量和對象的引用
Java中的七種排序方式代碼示例
分法 快速 eth san esc AR 升序 num 算法 package baseJava; /** * @title SortMethods.java * @author DonsenChen * @Date 2018年5月2日 上午10:16:03 *
Java中final與 static final 修飾的常量的區別
評論 tin 產生 建立 dom code 隨機數 ren 使用 喵喵開車,新手上路,多多關照。有任何錯誤請在評論區指出。 ...........................................我是萬惡的分界線( ? ?ω?? )?.............
Java中session與application的異同
導致 自動 客戶 器) 每一個 class ica span 關閉 客戶端的session 其實是標記了你的請求來自哪個瀏覽器 問題1:永遠都一樣嗎? 答:重啟了瀏覽器,你的session id就改變了, 結果會導致,再無法取回原來在服務端保存的數據。 問題2:
java中a++與++a區別
demo div main highlight print class 結果 public 別了 java中a++與++a區別 a++與++a的區別,如果單獨使用沒有任何區別,如果在運算中就有區別了,a++是先運算在賦值,而++a是先賦值在運算!! class dem
JAVA中所有與集合有關的實現類都是這六個接口的實現類
length 數字 pack 有關 結構 [] rgs val 無序 JAVA中所有與集合有關的實現類都是這六個接口的實現類。 Collection接口:集合中每一個元素為一個對象,這個接口將這些對象組織在一起,形成一維結構。 List接口代表按照元素一定的相關順序