为什么 Java 类应该实现可比性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3718383/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 03:53:45  来源:igfitidea点击:

Why should a Java class implement comparable?

java

提问by London

Why is Java Comparableused? Why would someone implement Comparablein a class? What is a real life example where you need to implement comparable?

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

采纳答案by Enno Shioji

Here is a real life sample. Note that Stringalso implements Comparable.

这是一个真实的生活样本。请注意,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;
    }
}

later..

之后..

/**
 * 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);
}

回答by Amir Rachum

The fact that a class implements Comparablemeans that you can take two objects from that class and compare them. Some classes, like certain collections (sort function in a collection) that keep objects in order rely on them being comparable (in order to sort you need to know which object is the "biggest" and so forth).

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

回答by Qwerky

Quoted from the javadoc;

引自 javadoc;

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.

Lists (and arrays) of objects that implement this interface can be sorted automatically by Collections.sort (and Arrays.sort).Objects that implement this interface can be used as keys in a sorted map or as elements in a sorted set, without the need to specify a comparator.

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

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

Edit: ..and made the important bit bold.

编辑:..并把重要的一点加粗。

回答by Fernando Miguélez

For example when you want to have a sorted collection or map

例如,当你想要一个排序的集合或地图时

回答by Steve B.

Comparable defines a natural ordering. What this means is that you're defining it when one object should be considered "less than" or "greater than".

Comparable 定义了自然排序。这意味着当一个对象应该被视为“小于”或“大于”时,您正在定义它。

Suppose you have a bunch of integers and you want to sort them. That's pretty easy, just put them in a sorted collection, right?

假设你有一堆整数,你想对它们进行排序。这很简单,只需将它们放在一个排序的集合中,对吗?

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

But now suppose I have some custom object, where sorting makes sense to me, but is undefined. Let's say, I have data representing districts by zipcode with population density, and I want to sort them by density:

但是现在假设我有一些自定义对象,其中排序对我有意义,但未定义。假设我有按人口密度按邮政编码表示地区的数据,我想按密度对它们进行排序:

public class District {
  String zipcode; 
  Double populationDensity;
}

Now the easiest way to sort them is to define them with a natural ordering by implementing Comparable, which means there's a standard way these objects are defined to be ordered.:

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

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

Note that you can do the equivalent thing by defining a comparator. The difference is that the comparator defines the ordering logic outside the object. Maybe in a separate process I need to order the same objects by zipcode - in that case the ordering isn't necessarily a property of the object, or differs from the objects natural ordering. You could use an external comparator to define a custom ordering on integers, for example by sorting them by their alphabetical value.

请注意,您可以通过定义比较器来做等效的事情。不同之处在于比较器定义了对象之外的排序逻辑。也许在一个单独的过程中,我需要按邮政编码对相同的对象进行排序 - 在这种情况下,排序不一定是对象的属性,或者与对象的自然排序不同。您可以使用外部比较器来定义整数的自定义排序,例如通过按字母值对它们进行排序。

Basically the ordering logic has to exist somewhere. That can be -

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

  • in the object itself, if it's naturally comparable (extends Comparable -e.g. integers)

  • supplied in an external comparator, as in the example above.

  • 在对象本身中,如果它是自然可比的(扩展 Comparable -eg integers)

  • 由外部比较器提供,如上例所示。

回答by arviman

Most of the examples above show how to reuse an existing comparable object in the compareTo function. If you would like to implement your own compareTo when you want to compare two objects of the same class, say an AirlineTicket object that you would like to sort by price(less is ranked first), followed by number of stopover (again, less is ranked first), you would do the following:

上面的大多数示例展示了如何在 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;            
    }
}

回答by Ran Adler

An easy way to implement multiple field comparisons is with Guava's ComparisonChain- then you can say

实现多字段比较的一种简单方法是使用Guava 的比较链- 那么你可以说

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

instead of

代替

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

回答by nono

Comparable is used to compare instances of your class. We can compare instances from many ways that is why we need to implement a method compareToin order to know how (attributes) we want to compare instances.

Comparable 用于比较类的实例。我们可以通过多种方式比较实例,这就是为什么我们需要实现一个方法compareTo才能知道我们想要比较实例的方式(属性)。

Dogclass:

Dog班级:

package test;
import java.util.Arrays;

public class Main {

    public static void main(String[] args) {
        Dog d1 = new Dog("brutus");
        Dog d2 = new Dog("medor");
        Dog d3 = new Dog("ara");
        Dog[] dogs = new Dog[3];
        dogs[0] = d1;
        dogs[1] = d2;
        dogs[2] = d3;

        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * brutus
         * medor
         * ara
         */

        Arrays.sort(dogs, Dog.NameComparator);
        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * ara
         * medor
         * brutus
         */

    }
}

Mainclass:

Main班级:

package test;

import java.util.Arrays;

public class Main {

    public static void main(String[] args) {
        Dog d1 = new Dog("brutus");
        Dog d2 = new Dog("medor");
        Dog d3 = new Dog("ara");
        Dog[] dogs = new Dog[3];
        dogs[0] = d1;
        dogs[1] = d2;
        dogs[2] = d3;

        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * brutus
         * medor
         * ara
         */

        Arrays.sort(dogs, Dog.NameComparator);
        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * ara
         * medor
         * brutus
         */

    }
}

Here is a good example how to use comparable in Java:

这是如何在 Java 中使用可比较的一个很好的例子:

http://www.onjava.com/pub/a/onjava/2003/03/12/java_comp.html?page=2

http://www.onjava.com/pub/a/onjava/2003/03/12/java_comp.html?page=2

回答by lxknvlk

When you implement Comparableinterface, you need to implement method compareTo(). You need it to compare objects, in order to use, for example, sorting method of ArrayListclass. You need a way to compare your objects to be able to sort them. So you need a custom compareTo()method in your class so you can use it with the ArrayListsort method. The compareTo()method returns -1,0,1.

实现Comparable接口时,需要实现方法compareTo()。您需要它来比较对象,例如为了使用ArrayList类的排序方法。您需要一种方法来比较您的对象,以便能够对它们进行排序。因此compareTo(),您的类中需要一个自定义方法,以便您可以将它与ArrayListsort 方法一起使用。该compareTo()方法返回 -1,0,1。

I have just read an according chapter in Java Head 2.0, I'm still learning.

我刚刚阅读了 Java Head 2.0 中的相应章节,我仍在学习。

回答by Ale B

OK, but why not just define a compareTo()method without implementing comparable interface. For example a class Citydefined by its nameand temperatureand

好的,但为什么不只定义一个compareTo()方法而不实现可比较的接口。例如一个City由它nametemperature和定义的类

public int compareTo(City theOther)
{
    if (this.temperature < theOther.temperature)
        return -1;
    else if (this.temperature > theOther.temperature)
        return 1;
    else
        return 0;
}