比较器和java中的类似实现

时间:2012-12-04 16:41:54

标签: java comparator comparable

我知道这些接口用于Collection中的排序对象。但我怀疑这些的真正区别。我读到的一个事实是,当你想要将两个对象与当前对象(这个)进行比较时,使用可比性。

但我的问题是甚至比较我们比较相同的对象类型知道。

这里有什么不同。我很迷惑。 假设以下示例

class Person implements Comparable<Person> {
  private String firstName;
  private String lastName;
  private int age;

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

  public int compareTo(Person anotherPerson){     
    int anotherPersonAge =anotherPerson.getAge();  
    return this.age - anotherPersonAge;    
  }
}

如果我使用比较器,我会有一个类实现比较器,而不是this.age,它有person.age。那么这里有什么不同呢?

public class LastNameComparator implements Comparator<Person> {
  public int compare(Person person, Person anotherPerson) {
    int age1 = person.getAge();
    int age2 = anotherPerson.getAge();

     return age1 - age2; 
  }
}

我不知道Collections.sort使用的内部逻辑。如果是这样的话,请证明上述观点是合理的。

另外我认为不需要返回-1,1或0。以上实施也有效吗?我遇到的一个问题是,如果我们返回1,列表如何按照升序或降序对项目进行排序?我认为差异考虑并根据差异对它们进行排序。

5 个答案:

答案 0 :(得分:1)

考虑Comparable

的文档
  

此接口对每个类的对象施加总排序   实现它。这种排序称为类   自然排序,类的compareTo方法称为   它的自然比较方法。

Comparator

  

比较函数,对某些函数施加总排序   对象的集合。可以将比较器传递给排序方法   (例如Collections.sort或Arrays.sort)允许精确控制   超过排序顺序。比较器也可用于控制订单   某些数据结构(如排序集或排序映射)或   为没有的对象集合提供排序   自然排序。

Comparable对象可以通过将自身与另一个对象(自然排序)进行比较来确定其顺序,而Comparator是一个知道如何比较两个对象并确定其特定顺序的对象。这里的不同之处在于谁负责比较。

自然排序使用compareTo强加定义的顺序,但如果您想要更改该顺序,或者更糟糕的是,没有定义的比较逻辑,该怎么办?这里是Comparator派上用场的地方,因为您可以根据不同的比较对集合进行排序,这些比较可以通过发布新的Comparator动态切换,而不是一些令人讨厌的逻辑,您应该告诉{{1}对象“嘿,现在你按照名字而不是年龄订购”。

关于比较结果之间的差异,检查每个对象。例如,请年龄为Comparable1015的三个人。 2015相比时返回1,但与10相比,返回-1,定义了三个人的顺序。

选择适合您需求的方法。如果您的比较逻辑稳定且将来不会更改,您可能希望拥有20个对象,但是您是否需要根据Comparable s的不同标准对集合进行排序

答案 1 :(得分:0)

快速扫描java.util.Collections javadocs提供了这个:

  

public static void sort(列表列表) -       根据元素的自然顺序,将指定列表按升序排序。 列表中的所有元素都必须实现Comparable接口。此外,列表中的所有元素必须是可相互比较的(即,e1.compareTo(e2)不得对列表中的任何元素e1和e2抛出ClassCastException。)

     

public static void sort(列表列表,                           比较者c) -   根据指定比较器引发的顺序对指定列表进行排序。 列表中的所有元素必须使用指定的比较器进行相互比较(即,c.compare(e1,e2)不得为列表中的任何元素e1和e2抛出ClassCastException。) p>

可以推断,sort(List list)然后使用Comparable接口,sort(List list, Comparator c)使用比较器。

要回答你的最后一个问题,以你描述的方式使用这两种方法没有区别......这两种方法的目的是让你可以用不同的方式比较对象,而不是以相同的方式使用不同的实现。

答案 2 :(得分:0)

以这种方式考虑......你有Class IntegerWrapper ,它有一个整数,你在类中实现了 Comparable 。因此,当使用Collection.sort对它们进行排序时......它将按升序为您提供对象...

但是当您想要更改此订单并希望降序订单时,您必须实施比较器以按所需顺序对其进行排序...

答案 3 :(得分:0)

在Java中,类型总是只能实现一次接口,就是你不能说

public class Foo implements Comparable<Foo>, Comparable<String> {}

这意味着Foo的实例将始终以某种方式排序 - 您不能让排序在某个上下文中以某种方式表现,而在另一种上下文中则不同。

另一方面,Comparator与它可以排序的实例无关。对于单个类型,您可以拥有尽可能多的Comparator个(而不是一个Comparable)。如果您需要某种排序,只需创建一个新的Comparator即可。

编写一个对不同类型的实例进行排序的Comparator也很容易 - 这对Comparable很难处理,因为所有涉及的实例都必须彼此了解:任何实例都可以获得任何其他实例instance作为compareTo()中的参数,它们必须实现一些通用接口等。

答案 4 :(得分:0)

当有人使用Comparable接口时,我总是很害怕,因为它几乎总是错误的选择。 Comparable用于定义自然顺序而不是用于排序。 Java知道必须满足的equals-hashcode契约。大多数开发人员都知道。但还有一个重要的合同:平等可比的合同。

这意味着:

a.equals(b)&lt; ==&gt; a.compareTo(b)== 0

在您的示例中,您不能在一个TreeSet中拥有两个具有相同年龄的不同人。