在 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);