测试小站: 处理网 回收帮 培训网 富贵论坛 老富贵论坛

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的实现方式。

posted @ 2021-12-20 15:39  linjingyg  阅读(182)  评论(0)    收藏  举报