为什么Java类可以实现可比性?

Lon*_*don 132 java

为什么Comparable使用Java ?为什么有人会Comparable在课堂上实施?您需要实施可比较的现实生活示例是什么?

Enn*_*oji 206

这是一个现实生活中的样本.注意,String也实现Comparable.

class Author implements Comparable<Author>{
    String firstName;
    String lastName;

    @Override
    public int compareTo(Author other){
        // compareTo should return < 0 if this is supposed to be
        // less than other, > 0 if this is supposed to be greater than 
        // other and 0 if they are supposed to be equal
        int last = this.lastName.compareTo(other.lastName);
        return last == 0 ? this.firstName.compareTo(other.firstName) : last;
    }
}
Run Code Online (Sandbox Code Playgroud)

后来..

/**
 * List the authors. Sort them by name so it will look good.
 */
public List<Author> listAuthors(){
    List<Author> authors = readAuthorsFromFileOrSomething();
    Collections.sort(authors);
    return authors;
}

/**
 * List unique authors. Sort them by name so it will look good.
 */
public SortedSet<Author> listUniqueAuthors(){
    List<Author> authors = readAuthorsFromFileOrSomething();
    return new TreeSet<Author>(authors);
}
Run Code Online (Sandbox Code Playgroud)

  • 我只想注意,通常你会想要覆盖`equals`(因此`hashCode`)以与`compareTo`方法一致.例如,如果您希望类与[`TreeSet`](http://docs.oracle.com/javase/6/docs/api/java/util/TreeSet.html)一起使用,那么这是必要的. (14认同)

Ste*_* B. 38

可比较定义了自然顺序.这意味着,你定义它,当一个对象应该被认为是"低于"或"大于".

假设你有一堆整数,你想要对它们进行排序.这很简单,只需将它们放入已排序的集合中,对吧?

TreeSet<Integer> m = new TreeSet<Integer>(); 
m.add(1);
m.add(3);
m.add(2);
for (Integer i : m)
... // values will be sorted
Run Code Online (Sandbox Code Playgroud)

但是,现在假设我有一些自定义对象,其中排序对我来说很有意义,而且是不确定的.比方说,我有人口密度邮政编码代表地区的数据,我想通过密度对它们进行排序:

public class District {
  String zipcode; 
  Double populationDensity;
}
Run Code Online (Sandbox Code Playgroud)

现在最简单的排序方法是通过实现Comparable以自然顺序定义它们,这意味着这些对象被定义为有序的标准方式:

public class District implements Comparable<District>{
  String zipcode; 
  Double populationDensity;
  public int compareTo(District other)
  {
    return populationDensity.compareTo(other.populationDensity);
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,您可以通过定义比较器来执行相同的操作.不同之处在于比较器定义了对象外部的排序逻辑.也许在一个单独的过程中,我需要通过zipcode订购相同的对象 - 在这种情况下,排序不一定是对象的属性,或者与对象的自然顺序不同.你可以使用一个外部比较,通过他们的字母值顺序进行排序他们定义自定义排序的整数,例如.

基本上,排序逻辑必须存在于某处.那可以是 -

  • 在对象本身,如果它自然可比(扩展Comparable -eg整数)

  • 如上例所示,在外部比较器中提供.


Qwe*_*rky 14

引自javadoc;

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

可以通过Collections.sort(和Arrays.sort)自动对实现此接口的对象的列表(和数组)进行排序.实现此接口的对象可用作有序映射中的键或有序集中的元素,而无需指定比较器.

编辑:..并使重要的位大胆.

  • 我会说,在你加粗的那个之后的句子*就像(如果不是更多)重要一样. (4认同)

Ami*_*hum 8

类实现Comparable意味着您可以从该类中获取两个对象并进行比较.某些类,如某些集合(集合中的排序函数)使对象保持顺序依赖于它们是可比较的(为了排序,您需要知道哪个对象是"最大"等等).


arv*_*man 7

上面的大多数示例都显示了如何在compareTo函数中重用现有的可比较对象.如果你想比较同一个类的两个对象,你想要实现你自己的compareTo,比如你想要按价格排序的AirlineTicket对象(较少排在第一位),然后是中途停留次数(再次,较少是排名第一),你会做以下事情:

class AirlineTicket implements Comparable<Cost>
{
    public double cost;
    public int stopovers;
    public AirlineTicket(double cost, int stopovers)
    {
        this.cost = cost; this.stopovers = stopovers ;
    }

    public int compareTo(Cost o)
    {
        if(this.cost != o.cost)
          return Double.compare(this.cost, o.cost); //sorting in ascending order. 
        if(this.stopovers != o.stopovers)
          return this.stopovers - o.stopovers; //again, ascending but swap the two if you want descending
        return 0;            
    }
}
Run Code Online (Sandbox Code Playgroud)


Ran*_*ler 6

实现多场比较的简单方法是使用Guava的ComparisonChain - 然后你可以说

   public int compareTo(Foo that) {
     return ComparisonChain.start()
         .compare(lastName, that.lastName)
         .compare(firstName, that.firstName)
         .compare(zipCode, that.zipCode)
         .result();
   }
Run Code Online (Sandbox Code Playgroud)

代替

  public int compareTo(Person other) {
    int cmp = lastName.compareTo(other.lastName);
    if (cmp != 0) {
      return cmp;
    }
    cmp = firstName.compareTo(other.firstName);
    if (cmp != 0) {
      return cmp;
    }
    return Integer.compare(zipCode, other.zipCode);
  }
}
Run Code Online (Sandbox Code Playgroud)