简体   繁体   English

Java中的比较器和可比较实现

[英]comparator and comparable implementation in java

I know those interfaces use for sort objects in a Collection. 我知道这些接口用于集合中的排序对象。 But I am having doubt of the real difference of those. 但是,我怀疑它们之间的真正区别。 One fact i read is use comparable when you want to compare two objects with out the current object (this). 当您想将两个对象与当前对象(本)进行比较时,我读到的一个事实是使用可比性。

But my problem is even with comparator we compare same object type know. 但是我的问题是,即使使用比较器,我们也可以比较相同的对象类型。

What is really the difference here. 这里真的有什么区别。 I am confused. 我很困惑。 Suppose the following example, 假设以下示例,

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;    
  }
}

If i use comparator i would have a class implement the comparator and instead of this.age, it has person.age. 如果我使用比较器,我将拥有一个实现比较器的类,而不是this.age,它具有person.age。 So what is so different here? 那么,这里有什么不同?

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

     return age1 - age2; 
  }
}

I dont know the internal logic Collections.sort use. 我不知道内部逻辑Collections.sort的使用。 Please justify the above point if so with regard to that. 如果是这样,请说明以上几点。

Also i believe no need to return -1,1 or 0 right. 我也相信没有必要返回-1,1或0。 Above implementation is also valid right? 上面的实现也有效吧? One problem i am having is if we return 1 how can the list order the item according to ascending or descending order? 我遇到的一个问题是,如果我们返回1,则列表如何根据升序或降序对项目进行排序? I thought its the difference take into consider and order them according to the difference. 我认为其差异要考虑并根据差异进行排序。

Consider the documentation for both Comparable 考虑可比文件

This interface imposes a total ordering on the objects of each class that implements it. 该接口对实现该接口的每个类的对象强加了总体排序。 This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method. 此排序称为类的自然排序,而该类的compareTo方法被称为其自然比较方法。

and Comparator 比较器

A comparison function, which imposes a total ordering on some collection of objects. 比较功能,对某些对象集合施加总体排序。 Comparators can be passed to a sort method (such as Collections.sort or Arrays.sort) to allow precise control over the sort order. 可以将比较器传递给排序方法(例如Collections.sort或Arrays.sort),以精确控制排序顺序。 Comparators can also be used to control the order of certain data structures (such as sorted sets or sorted maps), or to provide an ordering for collections of objects that don't have a natural ordering. 比较器还可以用于控制某些数据结构(例如排序集或排序映射)的顺序,或为没有自然顺序的对象集合提供排序。

A Comparable object can determine its order by comparing itself with another object (natural ordering), while a Comparator is an object that knows how to compare two objects and determine their particular order. Comparable对象可以通过与另一个对象进行比较来确定其顺序(自然顺序),而Comparator是知道如何比较两个对象并确定其特定顺序的对象。 The difference here is who is responsible for the comparation. 这里的区别在于谁负责比较。

Natural ordering imposes a defined order with compareTo but what if you wanted to change that order or, even worse, there is no defined comparation logic? 自然排序通过compareTo强制使用已定义的顺序,但是如果您想更改该顺序,或者更糟的是,没有已定义的比较逻辑怎么办? Here is where Comparator comes in handy, since you can sort a collection based on different comparations that can be switched dynamically by issuing a new Comparator , instead of some nasty logic where you should tell the Comparable object "Hey, now you order according to name instead of age". 这是Comparator派上用场的地方,因为您可以基于不同的比较来对集合进行排序,这些比较可以通过发出新的Comparator器来动态切换,而不是一些讨厌的逻辑,您应该告诉Comparable对象“嘿,现在您按名称排序而不是年龄”。

Regarding the differences between the results of a comparation, they are checked for each object. 关于比较结果之间的差异,对每个对象进行检查。 For example, take three persons with age 10 , 15 and 20 . 例如,采取三人随着年龄的101520 15 returns 1 when compared with 10 but returns -1 when compared with 20 , defining the order of the three persons. 1510比较时返回-1 ,与20比较时返回-1 ,定义了三个人的顺序。

Choose the approach that fits your needs. 选择适合您需求的方法。 If your comparation logic is stable and won't be changed in the future, you might want to have Comparable objects, but should you need to sort a collection based on different criteria you should go for Comparator s. 如果您的比较逻辑是稳定的并且以后不会更改,则您可能希望拥有Comparable对象,但是如果需要根据不同的条件对集合进行排序,则应该使用Comparator

A quick scan of the java.util.Collections javadocs provides this: 快速扫描java.util.Collections javadocs提供了以下内容:

public static void sort(List list) - Sorts the specified list into ascending order, according to the natural ordering of its elements. public static void sort(List list)-根据指定元素的自然顺序将指定列表升序排序。 All elements in the list must implement the Comparable interface . 列表中的所有元素必须实现Comparable接口 Furthermore, all elements in the list must be mutually comparable (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the list). 此外,列表中的所有元素必须相互可比较(也就是说,对于列表中的任何元素e1和e2,e1.compareTo(e2)均不得抛出ClassCastException)。

public static void sort(List list, Comparator c) - Sorts the specified list according to the order induced by the specified comparator. public static void sort(List list,Comparator c)-根据指定比较器所诱导的顺序对指定列表进行排序。 All elements in the list must be mutually comparable using the specified comparator (that is, c.compare(e1, e2) must not throw a ClassCastException for any elements e1 and e2 in the list). 列表中的所有元素都必须使用指定的比较器进行相互比较 (即c.compare(e1,e2)不得对列表中的任何元素e1和e2抛出ClassCastException。

It can be inferred that sort(List list) then uses the Comparable interface and sort(List list, Comparator c) uses a comparator. 可以推断出sort(List list)然后使用Comparable接口, sort(List list, Comparator c)使用比较器。

To answer your final question, there is no difference between using the two methods in the way that you describe... the purpose of having the two methods is so you can compare objects in different ways, not in the same way using different implementations. 要回答您的最后一个问题,以您描述的方式使用这两种方法没有什么区别。拥有这两种方法的目的是使您能够以不同的方式比较对象,而不是以不同的方式使用不同的实现。

Consider in this way... You have Class IntegerWrapper which has one integer, and you implemented Comparable in the class. 以这种方式考虑...您拥有具有一个整数的Class IntegerWrapper ,并且在该类中实现了Comparable So when sorting these using Collection.sort... It will give you objects in ascending order... 因此,当使用Collection.sort对它们进行排序时...它会为您提供升序的对象...

But when you want to change this order and wants descending order, then you must implement comparator to sort them in desired order... 但是当您想更改此顺序并希望降序时 ,则必须实现比较器以按所需顺序对其进行排序...

In Java, a type can always only ever implement an interface once, that is you can't say 在Java中,类型永远只能实现一次接口,也就是说,您不能说

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

This means the instances of Foo will always sort in a certain way - you can't have the sorting behave one way in a certain context and differently in another context. 这意味着Foo的实例将始终以某种方式进行排序-您不能使排序在某种情况下的行为与另一种情况的行为不同。

The Comparator , on the other hand, is independent of the instances it can sort. Comparator ,在另一方面,是独立可排序的实例。 You can have as many Comparator s for a single type (as opposed to exactly one Comparable ). 单个类型可以具有多个Comparator (与完全相同的Comparable相对)。 If you need a certain sorting, just create a new Comparator and you're done. 如果您需要某种排序,只需创建一个新的Comparator

It's also easy to write a Comparator that sorts instances of different types - this is hard to do with Comparable because all involved instances would have to know about each other: Any instance could get any other instance as argument in compareTo() and they would have to implement some common interface, etc. 编写Comparator对不同类型的实例进行排序也很容易-使用Comparable很难做到这一点,因为所有涉及的实例都必须彼此了解:任何实例都可以将其他实例作为compareTo()参数,并且实现一些通用接口等

I'm always frighted when some uses the Comparable interface because it is nearly always the wrong choice. 当有人使用Comparable接口时,我总是会感到害怕,因为它几乎总是错误的选择。 Comparable is used to define a natural order and not for sorting. 可比用于定义自然顺序,而不用于排序。 Java knows the equals-hashcode contract that must be fulfilled. Java知道必须满足的equals-hashcode合同。 The most developers know it. 大多数开发人员都知道。 But there is an additional important contract: The equals-comparable contract. 但是还有另外一个重要的合同:可比合同。

That means: 这意味着:

a.equals(b) <==> a.compareTo(b) == 0 a.equals(b)<==> a.compareTo(b)== 0

In your example you cannot have two different persons with the same age in one TreeSet. 在您的示例中,您不能在一个TreeSet中拥有两个具有相同年龄的不同人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM