我們在學習java基礎的時候知道,基本數據類型數組可以直接調動Arrays類的靜態sort方法,然后輸出。
例如: int iArr[] = {1,2,4,6}; Arrays.sort(iArr); 然后利用for循環輸出..
但是如果我們是對象數組的話,則對象所在的類必須實現comparable接口,覆寫它的compareTo方法,並且要有不同的返回值,代表升序和降序。
但是會有一個疑問:為什么對象數組調用Arrays.sort 必須要實現comparable接口呢?而且compareTo的返回值到底代表什么意義呢,它又是如何決定數組的升序和降序的呢?
帶着這樣的疑問,我自己寫了一個很簡單的例子,然后進行調試,跟進源碼,終於發現的一點端倪,然后把我自己理解分享給大家
關於如何進入源碼,以及查看源碼中與變量有關的信息我的有一篇博客講到 補充 ,有時間可以去看下。。
接下來上代碼://Test類 package TEST;
接下來我們加入斷點進行調試
首先我們進入方法1: Arrays.class中的sort()方法
接下來進入方法2:ComparableTimSort.class 的sort()方法
下一步進入:方法3:ComparableTimSort.class的countRunAndMakeAscending方法里面終於見到了我們的CompareTo方法
這里你應該終於明白了為什么一定要實現comparable接口中的compareTo方法了吧。
如何你沒有實現,那么通過接口去找compareTo方法肯定會報錯啊(因為這時候找不到compareTo方法,未定義)
結合Test類中的compareTo方法,當this.age<o.age時,返回-1;
所以進入while循環,直到 a[runHi]).compareTo(a[runHi - 1])>=0時結束循環,后反轉對象數組的lo~runHi-1部分
(ComparableTimSort.class)reverseRange(a, lo, runHi)的源碼如下:
private static void reverseRange(Object[] a, int lo, int hi) { hi--; while (lo < hi) { Object t = a[lo]; a[lo++] = a[hi]; a[hi--] = t; } }
此時經過反轉后數組變為了 2, 5, 6, 3, 1(這里沒有寫name屬性),也就是前面3個對象是有序的,升序接下來我們就進入了下一個方法(ComparableTimSort.class)
我花了一點時間看了一下,就是C語言數據結構的二分排序法(也叫折半插入法,它是插入排序的一種改進版)
基本思想是:現將部分數組的部分元素變成一個有序的數組,后面的元素通過折半插入將它變成一個有序的數組。
例如前文:數組變成了2,5,6,3,1
則3插入前面有序的數組中,變成了 2,3,5,6,1
1在插入前面有序的數組中,變成了1,2,3,5,6
大家有時間可以去研究下。。這里不做詳細說明。到了這里方法基本都跟進並介紹完了
輸出結果:
1ii
2kk
3tt
5ss
6paul 升序。
那如何是降序呢?
修改Test類中的compareTo方法:
public int compareTo(Test o) { if (this.age > o.age) return -1; return 1; }
將返回值調換就行了,輸出結果:
6paul
5ss
3tt
2kk
1ii 降序
關於compareTo方法的實現及返回值以下的組合,譬如:
public int compareTo(Test o) { if (o.age > this.age){ return 1; return -1; }
public int compareTo(Test o)
{
if (o.age > this.age)
return -1;
return 1;
}
那他們到底是升序還是降序呢?自己結合源碼可以去思考一下。
但是上面兩種不建議寫,因為容易混淆。推薦寫最上面兩種。。。
寫了這么多 總結一下:
//升序 public int compareTo(Test o) { if (this.age>o.age ){ return 1; return -1; } //降序 public int compareTo(Test o) { if (this.age > o.age) return -1; return 1; }
我自己記憶的方法是:
大於號 返回1,正乘正為正,所以升序(可以把>號想象為正)
大於號返回-1,正乘負為負,所以降序
提示非常重要的一點,compareTo中的方法一定要有至少兩個以上(其實兩個足夠)的返回值,而且一個返回值一定要小於0,另一個一定要大於或等於0。
否則排序不會成功。自己結合ComparableTimSort.class的countRunAndMakeAscending方法分析。
最后留一個問題:我們說可以按照年齡屬性進行降序升序排序,但比如有如下要求。
要求按照年齡大小升序排列,當年齡相同時,按照name屬性降序排列,這時候compareTo函數怎么寫呢?
大家可以去思考一下,這里我就不貼代碼出來了,相信大家看過前文,自己思考一下應該可以寫出來。
好了,這個博客寫了好多小時了,該結束了,現在是北京時間22:25。撤了,撤了,大家晚安。
2017/6/19/ 22:25 ---祥子