java中的Comparator和Comparable區別講解
在java中實現比較功能是很容易的。當遇到自定義型別,或比較物件不能直接進行比較,我們需要使用比較策略,通過Comparator 或 Comparable 介面即可簡單實現。
示例準備
假設有一個足球隊,我們想給其中運動員按照其等級進行排序,簡單定義Player類:
示例程式碼如下:
public class Player {
private int ranking;
private String name;
private int age;
// constructor, getters, setters
@Override
public String toString() {
return this.name;
}
}
接下來,我們建立PlayerSorter類,往集合中增加一些物件,嘗試使用Collections.sort方法進行排序:
@Test
public void test1() {
List footballTeam=new ArrayList<>();
Player player1=new Player(59, "John", 20);
Player player2=new Player(67, "Roger", 22);
Player player3=new Player(45, "Steven", 24);
footballTeam.add(player1);
footballTeam.add(player2);
footballTeam.add(player3);
System.out.println("Before Sorting : " + footballTeam);
Collections.sort(footballTeam);
System.out.println("After Sorting : " + footballTeam);
}
上面程式碼執行時會報錯:
The method sort(List) in the type Collections
is not applicable for the arguments (ArrayList)
下面我們解釋我們那裡出錯了。
Comparable
見名思意,Comparable介面定義了相同兩個物件之間比較策略,稱為類的“自然排序”。因此為了排序,我們必須讓Player物件實現Comparable介面:
public class Player implements Comparable {
//...
@Override
public int compareTo(Player otherPlayer) {
return (this.getRanking() - otherPlayer.getRanking());
}
}
compareTo方法的返回值決定物件順序。方法返回數值表明被比較物件是否小於、等於或大於傳入引數物件。
執行程式,結果Player按照ranking進行排序:
Before Sorting : [John, Roger, Steven]
After Sorting : [Steven, John, Roger]
現在我們應該理解了利用Comparable介面實現物件自然排序。下面讓我們看看其他型別的排序,比直接實現介面更靈活的方式。
Comparator
Comparator 介面定義了 compare(arg1, arg2) 方法,其兩個引數代表比較物件,機制類似於 ComparablepareTo() 方法.
建立比較器
為了建立Comparator(比較器),我們需要實現Comparator介面。首先,我們建立一個Comparator,使用Player的ranking屬性進行排序:
public class PlayerRankingComparator implements Comparator {
@Override
public int compare(Player firstPlayer, Player secondPlayer) {
return (firstPlayer.getRanking() - secondPlayer.getRanking());
}
}
類似地也能建立Comparator,使用Player的age屬性進行排序:
public class PlayerAgeComparator implements Comparator {
@Override
public int compare(Player firstPlayer, Player secondPlayer) {
return (firstPlayer.getAge() - secondPlayer.getAge());
}
}
實現比較
為了演示這個概念,我們使用Collections.sort的另一個過載方法,帶有兩個引數,其中第二個引數需要Comparator 例項。
使用這種方法,能夠覆蓋自然排序:
PlayerRankingComparator playerComparator=new PlayerRankingComparator();
Collections.sort(footballTeam, playerComparator);
執行測試結果如下:
Before Sorting : [John, Roger, Steven]
After Sorting by ranking : [Steven, John, Roger]
如果我們需要不同的排序方式,僅需要傳遞不同的Comparator:
PlayerAgeComparator playerComparator=new PlayerAgeComparator();
Collections.sort(footballTeam, playerComparator);
執行測試結果如下:
Before Sorting : [John, Roger, Steven]
After Sorting by age : [Roger, John, Steven]
Java 8 的比較實現
java 8提供了新的方式定義比較器,使用lambda表示式和靜態工廠方法comparing()。
下面通過簡單示例lambda表示式說明。
Comparator byRanking
=(Player player1, Player player2) -> player1.getRanking() - player2.getRanking();
靜態工廠方法comparing()引數需要方法計算屬性進行排序,返回合適的比較器示例:
Comparator byRanking=Comparator
paring(Player::getRanking);
Comparator byAge=Comparator
paring(Player::getAge);
更多java8比較實現以後單獨進行解釋。
Comparator Vs Comparable
Comparable 介面適合定義預設排序方式,換句話說,是物件的主要排序方式。那麼,我們已經有了Comparable ,為什麼還要使用Comparator ?下面列舉幾個原因:
有時,我們不能修改類的原始碼,我們想實現其物件排序,使用Comparable介面不現實。 使用Comparators,我們可以不修改比較類程式碼 我們可以定義多個Comparators策略,實現不同的排序方式,Comparable實現不了。
總結
本文我們學習了java的比較策略,主要介紹了Comparator 或 Comparable 介面實現方式,並對比了兩者之間的差異。同時簡單介紹了java8的實現方式。