【问题标题】:Difference between Comparable and Comparator?可比和比较器之间的区别?
【发布时间】:2018-03-29 18:26:26
【问题描述】:

我的理解是 Comparator 可以比较来自不同类的多个对象,而 Comparable 只能将一个对象与同一类中的另一个实例进行比较。

比较 (object1) 比较(object1,object2)

上面的解释是真的吗??

【问题讨论】:

  • 比较器 - 两个参数的类型必须相同

标签: java oop


【解决方案1】:

不是。
ComparableComparator 是通用接口,允许比较泛型中定义的类型的实例(包括子类)。

它们之间的主要区别在于Comparable 是直接在要比较对象的类中实现的。

因此,如果您只有一种方法来比较类中的实例,即您对它们有一个自然的顺序,那么Comparable 是正确的方法。
另一方面,如果您有多种方法来比较一个类中的实例,Comparable 是不够的。
您应该改用Comparators(如果它不存在自然顺序)或同时使用两者(如果它存在自然顺序和其他一些类型的顺序)。


Comparator 除了Comparable 之外还有用处的示例:

String 类通过按字典顺序比较两个字符串来实现 Comparable。 假设您需要根据不同的规则对String 中的List 进行排序:它们的长度。
您将需要定义一个实现此规则的Comparator<String>,例如:

public class StringLengthComparator implements Comparator<String> {

    @Override
    public int compare(String o1, String o2) {
        return Integer.compare(o1.length(), o2.length());
    }

}

现在您可以使用Strings 的自然顺序对它们进行排序(使用Comparable):

List<String> strings = new ArrayList<>();
...
strings.sort();

但您也可以使用特定的Comparator&lt;String&gt;

strings.sort(new StringLengthComparator());

或者不使用 lambda 创建任何类:

strings.sort((o1,o2)->Integer.compare(o1.length(), o2.length()));

应使用Comparator 代替Comparable 的示例:

假设您有一个代表银行帐户的 Account 类。
从功能上讲,您没有对它们进行排序的自然顺序,而是根据客户的需要有多个订单。 让类实现Comparable 是没有意义的。但是创建不同的Comparator&lt;Account&gt; 会。


只能使用Comparator的情况:

如果要为无法更改源代码的类(JDK 类或第三方类)的实例定义顺序,Comparator 是遵循的方式。

【讨论】:

  • 感谢您的回答。你能告诉我一个小代码,其中演示了比较器接口的用法吗?
  • @Smith 当然。我添加了一个示例。
【解决方案2】:

此答案基于从 Intertech Training 的 Complete Java SE 8 Developer Bootcamp 课程中提取的信息。据他们说

Comparable 界面显示“这个特定对象将 与另一个对象相比”,而 Comparator 有点像 这个第三方“给我任何两个对象,我会告诉你如何 他们是订购的”。

ComparableComparator都位于java.util.package

字符串、图表、整数等都具有“自然排序”(遵循 unicode,因此排序的最高优先级是数字,然后是大写字母和小写字母)。如果我们要对自定义类进行排序,那么我们必须实现一个 Comparable 接口来帮助排序方法理解它们应该做什么(让 Collections 或 Arrays 对你的类型进行排序,类型必须实现 Comparable 接口)。

实现 Comparable 接口的类必须实现compareTo() 方法。此方法采用通用对象。例如,

public class MyDate implements Comparable {
    private int day, month, year;
    public MyDate(int month, int day, int year) {
        this.day = day;
        this.year = year;
        this.month = month;
    }
    public int compareTo(Object o) {
        MyDate d = (MyDate) o;
        if (year != d.year) {
            return year - d.year;
        }
        if (month != d.month ) {
            return month - d.month;
        }
        if (day != d.day) {
            return day - d.day;
        }
        return 0;
    }
    ...
}

实现Comparator 接口的类必须实现compare() 方法。此方法接受两个对象作为参数,如果第一个参数大于第二个参数,则返回正数,如果相等则返回零,否则返回负数。

public class MyDate implements Comparator {
    private int day, month, year;
    public MyDate(int month, int day, int year) {
        this.day = day;
        this.year = year;
        this.month = month;
    }
    public int compare(Object o1, Object o2) {
        MyDate d1 = (MyDate) o1;
        MyDate d2 = (MyDate) o2;
        if (d1.year != d2.year) {
            return d1.year - d2.year;
        }
        if (d1.month != d2.month ) {
            return d1.month - d2.month;
        }
        if (d1.day != d2.day) {
            return d1.day - d2.day;
        }
        return 0;
    }
    ...
}

Comparator 可用于比较任意两个对象。在比较同类对象时,最好尽可能使用Comparable接口。

比较器在比较异构集合的元素和我们没有源的第三方类时很有用。

【讨论】:

    【解决方案3】:

    我认为,当我们想通过多个属性自然地比较用户定义的类时,最好使用 Comparator 接口,它允许我们创建一些实现比较器接口的类并比较每个属性。在这种情况下,我们有一个下面的代码:

    public class Student{
    private String name;
    private String ranking;
    private int age;
    private String country;
    
    // getter and setter
    }
    
    public class NameComparator implements Comparator{
    //compare by name attribute
    }
    public class AgeComparator implements Comparator{
    //compare by Age attribute
    }
    public class CountryComparator implements Comparator{
    //compare by Country attribute
    }
    public class RankingComparator implements Comparator{
    //compare by Ranking attribute
    }
    

    但是当我们想通过只使用一个属性来比较用户定义的类时,不需要比较器,我们可以使用可比较的接口来代替它,如下代码:

    public class Student{
    private String name;
    private String ranking;
    private int age;
    private String country;
    
    // getter and setter
    
    public int CompareTo(Object obj1){
    //implement comparation by name or age or etc
    }
    }
    

    如果我们使用 Comparator 接口,其中一个好处是用于内置类,这些类已经实现了 CompareTo 方法,例如 number 等。

    【讨论】:

      猜你喜欢
      • 2012-08-26
      • 1970-01-01
      • 2022-01-18
      • 2010-11-19
      • 1970-01-01
      • 2014-09-17
      • 1970-01-01
      • 1970-01-01
      • 2021-10-20
      相关资源
      最近更新 更多