1. 程式人生 > 其它 >java中的Comparator和Comparable區別講解

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的實現方式。