日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java arrays.sort() c_5.4 (Java学习笔记)集合的排序(Collections.sort(),及Arrays.sort())...

發布時間:2025/3/19 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java arrays.sort() c_5.4 (Java学习笔记)集合的排序(Collections.sort(),及Arrays.sort())... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.Comparable接口

這個接口顧名思義就是用于排序的,如果要對某些對象進行排序,那么該對象所在的類必須實現

Comparabld接口。Comparable接口只有一個方法CompareTo(),這個方法可以看做是指定的排序規則。

內置類已經實現了CompareTo方法,例如long

小于返回-1,等于返回0,大于返回1.

這里只舉一個例子,例如int,double,Date等可以排序的內置類都已經實現了CompareTo方法,即指定了排序規則。

2.Collections.sort()和Arrays.sort()方法。

Colections是對集合進行操作的工具類,Collection.sort是對集合排序的方法。

Collections.sort()的底層實質是是調用Arrays.sort();

我們來看下Collections.sort()的源碼:

首先傳遞進去的集合必須是Comparable接口及其子類,而且后續會用到Comparable接口中的CompareTo方法。所以進行排序的類必須實現Comparable,

可以看出如果沒有實現Comparable接口,參數傳遞會出現錯誤。

我們點進list.sort()方法,就會看到下面代碼:

我們可以看到,它是先將集合轉換成數組,然后調用Arrays.sort()方法。

排序排完后又將數組中元素逐個放入集合。

我們接下點進Arrays.sort()方法的源碼:

參數有兩個,有一個之前轉換成數組的集合a,c是一種排序規則,后面會講到。沒有指定的話,會自動設置為null。

然后判斷是否有排序規則,有就調用使用排序規則的排序方法。這里看出當設置了排序規則c時,會進入使用排序規則的比較方法進行比較,

此時compareTo()是不起作用的,起作用的是排序規則c中的compare()方法。

接著進入sort().

我們可以看到這里有兩個排序算法,使用LegacyMergeSort.userRequested控制,第一個是歸并排序,也就是LegacyMergeSort.userRequested為true時進入的語句,

注意默認狀態下LegcyMergeSort是false,所以默認進去的是ComparableTimSort.sort()。這時一種優化的排序算法,有興趣可以去查詢下,當然這種算法比較復雜,

不便于理解。legactMergeSort()便于理解些,我們就先分析這個排序算法。

默認是進入ComparableTimSort(),要想進入legacyMergeSort()我們就需要設置下LegacyMergeSort.userRequested的值。

這時我們可以自己設置LegacyMergeSort.userRequested的值,這句話是加在main中Sort調用之前的。

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");

設置為true后我們進入的就是legcyMergeSort();

/*注意:

這里只是對排序算法的一種優化,排序時的規則是不變的的。

(例如我現在要進行升序排序,可以用很多算法,但是最后的結果一定是升序的。)

這里我們主要看CompareTo()方法返回值(1,0,-1)在排序中起到的作用,不關心具體算法的優化,有興趣的可以自行查閱相關算法。*/

那么我們這時就會進入gacyMergeSort();

我們點擊該方法,看它的代碼:

首先將存放集合數組的數組克隆,然后將克隆后的數組作為參數傳遞進aux,這里c為null進入第一個mergeSort();

進入mergeSort()我們可以看到:

我們先看傳遞進去的參數,srt,dest都是存放數據的數組,str是克隆的數組,dest是原數組,low=0,high=數組長度,off = 0;

首先定義了一個legth = high - low,得到的其實也是數組長度,

一開始進行一個判斷,長度小于INSERTIONSORT_THRESHOLD(常量7)就采用更適合長度小于7的數組的插入排序算法,

我們可以看到代碼中排序的依據是CompareTo()的返回值,如果返回值大于0則交換位置,反之則不交換。

如果不小于則采用適合數組長度大于7的其他排序方法。

后面還有更適合數組長度大于7的算法,這里沒有貼出這部分代碼,有興趣可自己去了解下。

(這里只是對排序算法執行次數的一種優化,排序時的規則是不變的的。我們這里主要看CompareTo方法起到作用,不關心排序算法的優化。)

這里我們舉一個簡單的例子,假設現在我在鏈表里面存放了三個long型數據312;

我們從調用Collections.Sort()方法開始分析源碼執行的過程,理解CompareTo方法的作用。

進入mergeSort()方法后,我們先來看下傳遞進來的參數:

dest[] = {3,1,2}, low = 0, high = 3(數組長度);

接下來分析代碼執行過程:

首先i=0,然后j = 0,不滿足條件直接跳出,然后i++

此時i = 1,j=1,此時將元素轉換為Comparable接口調用CompareTo方法根據之前看的long里面的Compare方法(Comparable)dest[0].compareTo(dest[1]) = 1.

如果沒有實現Comparable接口,這里轉型也會出現錯誤。

//調用ComparTo()返回值不清楚的,回到前面去看long里面CompareTo方法

交換dest[0],dest[1]位置,此時數組順序:132.,然后j--,不滿足循環條件直接跳出,執行i++。

此時i=2,j=2,(Comparable)dest[1].compareTo(dest[2]) = 1,交換dest[1],dest[2],此時數組順序:123.執行i++;

i=3,不滿足循環條件,退出執行retun,結束排序,最終數組順序:123;

大家可以自己結合CompareTo方法的返回值分析分析排序過程。

了解了CompareTo在排序中起到的作用后,平常我們在實現Comparable接口,

實現其中的CompareTo方法時我們就可以明確CompareTo的返回值。

例如,a

如果是a>b return 1,就變成升序。分析源碼后我們可以自己分析排序到是升序還是降序。

我們也可以這樣理解,如果返回1就代表交換這兩個元素位置。

//一般情況下大于返回1,等于返回0,小于返回-1,更符合我們的思維習慣,這時排序是升序

建議一般情況下這樣寫,此時是升序,如果是要求降序排列,改變返回值,將a>b return -1就是降序了。

再次聲明,要使用排序方法,必須實現Comparable接口。

我們來舉一個具體的例子。例如新聞,我們首先要看時間降序(即最近發生的新聞出現在最前面),

其次按點擊量降序(即點擊量多的出現在前面)。

那么我們結合CompareTo方法在排序時的作用來考慮時間和點擊量比較的返回值。

首先,最近發生的新聞排在前面,如果A新聞時間在B新聞時間后面(也就是A新聞發生的時間離我們最近),

越在后面的時間的數值越大,Date本質上也是一個long型數。那么最近發生的排在前面應該降序。也就是if(a時間> b時間)return -1;

如果時間相同,我們再來考慮點擊量,點擊量大的排在前面。

那么這也是一個降序,if(點擊量a > 點擊量b) return -1;

這里也可以用之前如果返回1,就代表交換位置,-1就不交換位置這樣來理解,理解的方式有很多種,

但歸根結底都是對源碼執行過程的分析,把握這一點就可以以不變應萬變。

接下來我們來看具體的代碼。

NewS類代碼

import java.text.DateFormat;

import java.text.SimpleDateFormat;

import java.util.Date;

public class News implements Comparable{

private String newsName;

private Date date;

private int click;

private String timeS;

public News(){}

public News(String newsName, Date date, int click){

setNewsName(newsName);

setDate(date);

setClick(click);

}

public String getNewsName() {

return newsName;

}

public void setNewsName(String newsName) {

this.newsName = newsName;

}

public Date getDate() {

return date;

}

public void setDate(Date date) {

this.date = date;

DateFormat china_time = new SimpleDateFormat("yyyy-MM-dd hh-mm-ss");

timeS = china_time.format(date);

}

public int getClick() {

return click;

}

public void setClick(int click) {

this.click = click;

}

public int compareTo(News o) {

// TODO Auto-generated method stub

if(this.getDate().after(o.getDate()))//這句話就是如果this.getDate()的值 > o.getDate(),就降序排列。

return -1;?????????????????????? //也可以理解為如果this.getDate()的值 >o.getDate(),則不交換位置,即降序。

if(this.getClick() > o.click)//如果this的點擊數大于o的點擊數則降序排列,即點擊量大的排在前面

return -1;?????????????? //如果this的點擊量大于o的點擊量,則不交換位置,即降序排列

return 1;

}

public String toString(){

return "標題:" + this.newsName + "時間" + timeS

+ "點擊量" + this.click + "\n";

}

}

運行代碼

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Collections;

import java.util.Comparator;

import java.util.Date;

import java.util.LinkedList;

import java.util.List;

public class TestCompare {

public static void main(String[] args) {

List newsList = new LinkedList<>();

newsList.add(new News("國慶高峰堵車,各景點爆滿!",new Date(),1000));//設置為當前時間

newsList.add(new News("國慶仍有大部分家里蹲!",new Date(System.currentTimeMillis()-60*60*1000),100));//設置為當前時間前一小時

newsList.add(new News("驚呆,游客竟在做這種事!!!",new Date(),10000));//設置為當前時間,點擊量10000

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");//設置為true進入legacySort()

System.out.println(newsList);

Collections.sort(newsList);

System.out.println(newsList);

}

}

運行結果://排序前新聞

[標題:國慶高峰堵車,各景點爆滿!時間2018-10-07 09-23-53點擊量1000

, 標題:國慶仍有大部分家里蹲!時間2018-10-07 08-23-54點擊量100

, 標題:驚呆,游客竟在做這種事!!!時間2018-10-07 09-23-54點擊量10000

]//排序后新聞

[標題:驚呆,游客竟在做這種事!!!時間2018-10-07 09-23-54點擊量10000

, 標題:國慶高峰堵車,各景點爆滿!時間2018-10-07 09-23-53點擊量1000

, 標題:國慶仍有大部分家里蹲!時間2018-10-07 08-23-54點擊量100

]

我們可以看到,首先按時間(距離我們最近發生的新聞排在最前面)進行排序,時間相同按點擊量排序。

我們可以看出mergeSort中使用Compareto方法只是判斷是否大于0,

當我們的CompareTo()返回的是0或-1時,for()語句中判斷都是false,那么我們能否在返回時不要-1,只返回0,1呢?

在當前方法(LeacySort()中的mergeSort())顯然是可以的,因為0 > 0,-1>0的結果是相同的。

你要確定你進去的是LeacySort()中的mergeSort(),最好設置如下語句:

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");

如果沒有設置的話LegcyMergeSort.userRequested默認為false,進去的就是另外一種排序算法,在另外一種算法中這樣設置是不行的。

當默認為false時,我們進入另外一個算法看下:(這個算法只是簡單點的過一遍,不分析具體步驟)

為false時進去的是ComparebleTimSort.sort();我們進入這個算法看下:

首先一個斷言,一般情況下都沒有問題,

然后nRemaing = hi - lo,hi是數組長度,lo是0.

MIN_MERGE是32。

接著就是根據數組a計算initRunLen的值,

我們先進入countRunAndMakeAscending();

但我們將-1也設置為0時,else后面的語句判斷的是返回值>=0。-1和0去判斷得到的結果是不同的。

這里會造成這個值有問題,而這個值需要傳遞到排序算法中,就會導致排序出現問題。News中的CompareTo方法的

返回值只有0,1的話這里的runHi - lo是3,如果是按照正常的1,0,-1來的話runHi - lo是2。這個可以結合源碼自己分析一下。

這個執行完之后就要將得到的值,傳入我們的排序算法中開始排序了。(上述分析都是基于之前代碼中創建的三個新聞對象來分析的)

返回runHi-lo后,我們回到上一級

我們將值傳入binarSort()中,然后點擊binarySort:

這個具體過程就不一一分析了,有興趣的可以分析下這些算法。

start就是之前的返回值(runHi - lo),如有只有1,0返回的是3,如果是正常的-1,0,1返回的是2.

我們來看第一個for語句,如果start是3就直接跳出循環(hi是數組長度,這里為3)不進行排序,原有數據不會發生變化。

如果是2,進行排序,最后輸出是按照規則排序好的數據。

大家可以試下修改上面代碼中Nwes的compareTo()方法的返回值和運行代碼中設置true,false的部分:

(1)將 return -1改成return 0,LegacyMergeSort.userRequested為false時,輸出未正常排序結果。

LegacyMergeSort.userRequested為true時,輸出正常排序結果。

結合上述內容理解下整個的過程。

無論是哪種排序方法,嚴格按照(1,0,-1)返回,都可以輸出對應邏輯排序結果。

結合例子、源碼與上述內容分析分析,就可以清楚的知道排序執行的流程以及compareTo()返回值的作用。

3.Comparator接口

Comparator和Comparable類似,底層實現是一樣的,理解了Comparable中CompareTo()方法的作用后

理解Comparator就很簡單了。

我們之前說的實現Comparable接口的CompareTo方法是寫在需要進行排序的類里面的,可以說這種方法就從屬于這個類。

但Comparator就不一樣了,它只是制定了一種排序規則,不需要從屬于誰,誰需要用這個規則拿來用就可以了。

具體的操作是,新建一個規則類,例如我要按照新聞點擊量排序,那么我可以把這個類命名為NwesClickSort

這個類需要實現Comparator接口,并且實現里面的ompare()方法。

我們來看下Comparator接口中compare方法:

這個作用和compareTo()方法的作用一樣,也是比較兩個值(o1,o2),然后返回1,0,-1.

使用compare排序時,就是調用這個方法來進行排序。

使用時,我們需要為NewsClickSort這個類實例化一個對象,這個對象代表一種排序規則。

然后將集合和對象(排序規則)傳遞到Collections.sort()中。

我們先來看個例子://這里面我們指定了一種排序規則,按照點擊量來排序,Nwes類還是之前的代碼,沒有任何修改。

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Collections;

import java.util.Comparator;

import java.util.Date;

import java.util.LinkedList;

import java.util.List;

public class TestCompare {

public static void main(String[] args) {

List newsList = new LinkedList<>();

newsList.add(new News("國慶高峰堵車,各景點爆滿!",new Date(),1000));//設置為當前時間

newsList.add(new News("國慶仍有大部分家里蹲!",new Date(System.currentTimeMillis()-60*60*1000),100));//設置為當前時間前一小時

newsList.add(new News("驚呆,游客竟在做這種事!!!",new Date(),10000));//設置為當前時間,點擊量10000

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");//設置為true進入legacySort()

System.out.println(newsList);

Collections.sort(newsList,new NewsClickSort());//傳遞進去的集合,和排序規則

System.out.println(newsList);

}

}

class NewsClickSort implements Comparator{

@Override

public int compare(News o1, News o2) {

if(o1.getClick() < o2.getClick()){

return 1;//這里寫得不是很規范,最好是加上等于返回0,最后小于返回-1.

}else{

return -1;

}

}

}

運行結果:

//排序前結果[標題:國慶高峰堵車,各景點爆滿!時間2018-10-10 08-40-50點擊量1000

, 標題:國慶仍有大部分家里蹲!時間2018-10-10 07-40-50點擊量100

, 標題:驚呆,游客竟在做這種事!!!時間2018-10-10 08-40-50點擊量10000

]//排序后結果

[標題:驚呆,游客竟在做這種事!!!時間2018-10-10 08-40-50點擊量10000

, 標題:國慶高峰堵車,各景點爆滿!時間2018-10-10 08-40-50點擊量1000

, 標題:國慶仍有大部分家里蹲!時間2018-10-10 07-40-50點擊量100

]

排序規則中只指定了點擊量,所以排序后的結果是按點擊量來排序的。

我們可以看到上面代碼也設置了

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");//

我們就來分析下使用comparator接口中的compare方法的執行過程。

第一步當然是點進main中的

Collections.sort

注意那個c,就是實例化的比較規則。

我們繼續點擊sort():

我們會發現和之前看Comparable接口排序的執行過程是一樣的。

只是這時候c是實例化的排序規則,不是null了。

繼續點擊sort()

這時c不等于null,所以進入后面的if(LegcyMergeSort.userRequested)進行判斷

前面說了默認LegayMergeSort.userRequested是false,這里我們設置了為true,

所以我們點進legacyMergeSort():

c不等于null,我們點進第二個分支:

我們會發現和之前sort排序過程及CompareTo()的實現思路是一樣的,只是一個調用的是compareTo方法,

一個調用的是c.compare()方法。

LegayMergeSort.userRequested為false時,也和之前分析的sort排序過程及compareTo()的實現思路是一樣的,區別只是一個調用

的是compareTo()方法,一個調用的是c.compare()方法。

LegayMergeSort.userRequested為false時的后續執行過程有興趣可以去看下,會發現和前面講的一樣。

到這里整個比較過程就很清楚了。

總結

以上是生活随笔為你收集整理的java arrays.sort() c_5.4 (Java学习笔记)集合的排序(Collections.sort(),及Arrays.sort())...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。