在 Collections 有許多排序比較等等的方法已經寫好,基本類型的比較可以直接使用,如
ArrayList al = new ArrayList(); for(int i=0; i<10; i++){ Random r = new Random(); al.add(r.nextInt(1000)); } Collections.sort(al);
在 al 中的元素將會由小到大排好,但是如果 al 中的元素並不是基本類型,而是自創類別,而想比較的是自創類別中的某個屬性值,那麼可以實作 Comparable 介面,再覆寫 compareTo 方法,如下
package com.example.helloworld; import java.util.Comparator; public class AccountDetail implements Comparable<Object>{ static int dataCount; public String time; public String money; public String remark; public AccountDetail(){ dataCount++; time = "0000/00/00"; money = "0"; remark = "0"; } public AccountDetail(String time,String money,String type){ dataCount++; this.time = time; this.money = money; this.remark = type; } @Override public int compareTo(Object another) { AccountDetail adAnother = (AccountDetail)another; if(Integer.valueOf(this.money)>Integer.valueOf(adAnother.money)) { return 1;// move element back } else if(Integer.valueOf(this.money)<Integer.valueOf(adAnother.money)){ return -1;//move element forward } else{ return 0; } } }
AccountDetail 裡面有 3 個屬性,分別為 time , money , remark , 在第 5 行實作 Comparable 介面, 接著第 27 行覆寫 compareTo 方法, 方法裡面就寫出自訂的比較規則, 只要注意回傳值,1 代表往前排, -1 代表往後排,這段程式碼就代表比較 money 並由小排到大,最後使用的方式如下
ArrayList<AccountDetail> al = new ArrayList<AccountDetail>(); for(int i=0; i<10 ;i++){ Random r = new Random(); al.add(new AccountDetail("testtime",""+r.nextInt(1000)+i,"testremark")); } Collections.sort(al);
第 1 ~ 6 行建立 ArrayList al, 最後第 8 行排序,就這麼簡單,不過使用 Comparable 介面的缺點是只能使用單種排序,如果還想針對 time , remark 做排序,可以使用 Comparator 介面,好處除了可對多種數值做排序外,也不必綁定在 AccountDetail 類別中,你可以把它封裝出來(不過我還是寫在一起)
package com.example.helloworld; import java.util.Comparator; import FoXxLib.FP; public class AccountDetail { static int dataCount; public String time; public String money; public String remark; public AccountDetail(){ dataCount++; time = "0000/00/00"; money = "0"; remark = "0"; } public AccountDetail(String time,String money,String type){ dataCount++; this.time = time; this.money = money; this.remark = type; } public MoneyComparator moneyComp(){ MoneyComparator mc = new MoneyComparator(); return mc; } public TimeComparator timeComp(){ TimeComparator tc = new TimeComparator(); return tc; } } class MoneyComparator implements Comparator<Object>{ @Override public int compare(Object lhs, Object rhs) { AccountDetail ad1 = (AccountDetail)lhs; AccountDetail ad2 = (AccountDetail)rhs; if(Integer.valueOf(ad1.money)>Integer.valueOf(ad2.money)){ return 1; } else if(Integer.valueOf(ad1.money)<Integer.valueOf(ad2.money)){ return -1; } else{ return 0; } } } class TimeComparator implements Comparator<Object>{ @Override public int compare(Object lhs, Object rhs) { int tempReturn =0; AccountDetail ad1 = (AccountDetail)lhs; AccountDetail ad2 = (AccountDetail)rhs; String[] tempstr1 = ad1.time.split("[/]"); int[] tempint1 = new int[tempstr1.length]; for(int i=0; i<tempstr1.length; i++){ tempint1[i] = Integer.valueOf(tempstr1[i]); } String[] tempstr2 = ad2.time.split("[/]"); int[] tempint2 = new int[tempstr2.length]; for(int i=0; i<tempstr2.length; i++){ tempint2[i] = Integer.valueOf(tempstr2[i]); } for(int i=0; i<tempint1.length; i++){ if(tempint1[i]>tempint2[i]){ tempReturn = -1; break; } else if(tempint1[i]<tempint2[i]){ tempReturn = 1; break; } else if(tempint1[i]==tempint2[i]) { tempReturn =0; } } return tempReturn; } }
先把原先使用 Comparator 介面 的部分註解掉(第 8 行, 第 30 ~ 49 行)
第 51 ~ 56 行建立並回傳 money 的比較器
第 58 ~ 63 行建立並回傳 time 的比較器
第 66 ~ 84 行為 money 比較器的定義, 先實作 Comparator 介面
第 69 行覆寫 compare 方法, lhs 和 rhs 各為比較的物件,至於 compare 的內容就自己定義了
第 86 ~ 129 行為 time 比較器的定義,由於 time 包含了年月日,必須先切割字串,再放入陣列中等待比較,第 109 ~ 123 行為比較的方法
最後使用的方式如下
Collections.sort(al, al.get(0).timeComp());
第 1 個參數為比較的內容,第 2 個參數為比較器, timeComp 會回傳 time 比較器,當然你也可以改為 al.get(0).moneyComp() , 來比較 money
注意事項:
1.如果使用 Comparator 介面,且和要比較的容器類別綁在一起(就是上述的 AccountDetail.java),必須注意當沒有產生任何元素,還要排序時,會出現錯誤,所以排序類別還是拆開比較好如下
package com.example.helloworld; import java.util.Comparator; public abstract class AD_Sort implements Comparator<Object>{ } class MoneyComparator extends AD_Sort{ @Override public int compare(Object lhs, Object rhs) { AccountDetail ad1 = (AccountDetail)lhs; AccountDetail ad2 = (AccountDetail)rhs; if(Integer.valueOf(ad1.money)>Integer.valueOf(ad2.money)){ return -1; } else if(Integer.valueOf(ad1.money)<Integer.valueOf(ad2.money)){ return 1; } else{ return 0; } } } class TimeComparator extends AD_Sort{ @Override public int compare(Object lhs, Object rhs) { int tempReturn =0; AccountDetail ad1 = (AccountDetail)lhs; AccountDetail ad2 = (AccountDetail)rhs; String[] tempstr1 = ad1.time.split("[/]"); int[] tempint1 = new int[tempstr1.length]; for(int i=0; i<tempstr1.length; i++){ tempint1[i] = Integer.valueOf(tempstr1[i]); } String[] tempstr2 = ad2.time.split("[/]"); int[] tempint2 = new int[tempstr2.length]; for(int i=0; i<tempstr2.length; i++){ tempint2[i] = Integer.valueOf(tempstr2[i]); } for(int i=0; i<tempint1.length; i++){ if(tempint1[i]>tempint2[i]){ tempReturn = -1; break; } else if(tempint1[i]<tempint2[i]){ tempReturn = 1; break; } else if(tempint1[i]==tempint2[i]) { tempReturn =0; } } return tempReturn; } }
然後使用的方式為
AD_Sort ads; ads = new MoneyComparator(); Collections.sort(al, ads);