概念:
Comparable & Comparator 都是用來實現集合中元素的比較、排序的,只是 Comparable 是在集合內部定義的方法實現的排序,Comparator是在集合外部實現的排序,所以,如想實現排序,就需要在集合外定義 Comparator 接口的方法 或 在集合內實現 Comparable 接口的方法。
其中,comparable位於java.util下,comparator位於java.lang中。
Comparable是一個對象本身就已經支持自比較所需要實現的接口,如String、Integer自己就實現了Comparable接口,可完成比較大小操作。自定義類要在加入list容器中後能夠排序,也可以實現Comparable接口,在用Collections類的sort方法排序時若不指定Comparator,那就以自然順序排序。所謂自然順序就是實現Comparable接口設定的排序方式。
Comparator是一個專用(自定義)的比較器,當這個對象使用默認的比較方式不能滿足要求時,可寫一個比較器來完成兩個對象之間大小的比較。Comparator體現了一種策略模式(strategy design pattern),就是不改變對象自身,而用一個策略對象(strategy object)來改變它的行爲。
使用:
Comparable 簡單, 只要實現 Comparable 接口的對象直接就成爲一個可以比較的對象,但是需要修改源代碼。
適用於: 在不同場景只對自定義對象按同種形式進行排序。(例如:在項目需求中,只需要對Person對象按年齡排序)
Comparator 的好處是使用靈活,不需要修改源代碼, 而是另外實現一個比較器, 當某個自定義的對象需要作比較的時候,把比較器和對象一起傳遞過去就可以比大小了, 並且在Comparator 裏面用戶可以自己實現複雜的可以通用的邏輯,使其可以匹配一些比較簡單的對象,那樣就可以節省很多重複勞動了(類似策略模式的優點)。
(1)Comparable:
實現Comparable接口要覆蓋compareTo方法, 在compareTo方法裏面實現比較:
public class Person implements Comparable {
String name;
int age
public int compareTo(Person another) {
int i = 0;
i = name.compareTo(another.name); // 使用字符串的比較
if(i == 0) { // 如果名字一樣,比較年齡, 返回比較年齡結果
return age - another.age;
} else {
return i; // 名字不一樣, 返回比較名字的結果.
}
}
}
這時我們可以直接用 Collections.sort( personList ) 對其排序了.
(2)Comparator
實現Comparator需要覆蓋 compare 方法:
//需要排序的類
public class Person{
String name;
int age
}
//再類的外部定義比較器
class PersonComparator implements Comparator {
public int compare(Person one, Person another) {
int i = 0;
i = one.name.compareTo(another.name); // 使用字符串的比較
if(i == 0) { // 如果名字一樣,比較年齡,返回比較年齡結果
return one.age - another.age;
} else {
return i; // 名字不一樣, 返回比較名字的結果.
}
}
}
示例:
《劍指offer》題目:
輸入一個正整數數組,把數組裏所有數字拼接起來排成一個數,打印能拼接出的所有數字中最小的一個。例如輸入數組{3,32,321},則打印出這三個數字能排成的最小數字爲321323。
import java.util.ArrayList;
import java.util.*;
public class Solution {
public String PrintMinNumber(int [] numbers) {
//直接利用字符串數組的排序 再將其拼接在一起
//在排序時,本題目用到了比較器comparator的複寫
String[] str = new String [numbers.length];
for(int i=0; i<numbers.length; i++){
str[i] = String.valueOf(numbers[i]);
}
Arrays.sort(str,new Comparator<String>(){
@Override
public int compare(String s1, String s2) {
String c1 = s1 + s2;
String c2 = s2 + s1;
return c1.compareTo(c2);
//此處的compareTo是String中本身就繼承的comparable接口,可以用於直接比較
}
});
String temp = "";
for(int i=0;i<numbers.length;i++){
temp+=str[i];
}
return temp;
}
}
上題中,在比較字符串組合的大小時,無法直接使用默認的comparable比較器,因此在比較是重新定義了一個比較器comparator後,再調用的Arrays.sort(str,new comparator{}),在這裏可以學習一下這種構造器的定義方法,在Arrays.sort中直接定義:
Arrays.sort(str,new Comparator<String>(){
@Override
public int compare(String s1, String s2) {
String c1 = s1 + s2;
String c2 = s2 + s1;
return c1.compareTo(c2);
//此處的compareTo是String中本身就繼承的comparable接口,可以用於直接比較
}
});
本文參考:https://blog.csdn.net/acema/article/details/7513269 ; https://blog.csdn.net/l_lhc/article/details/50596065