compare()和compareTo()有什么区别?


Answers:


160

JavaNotes

  • a.compareTo(b)
    可比较接口:比较值并返回一个int,该值指示值比较小于,等于还是大于。
    如果您的类对象具有自然顺序,则实现Comparable<T>接口并定义此方法。具有自然排序实现的所有Java类Comparable<T>-示例:String包装类BigInteger

  • compare(a, b)
    比较器界面: 比较两个对象的值。这是作为Comparator<T>接口的一部分实现的,通常的用途是定义一个或多个实现此功能的小型实用程序类,以通过对sort()数据结构(例如TreeMap和)进行排序,传递给诸如或供使用的方法TreeSet。您可能想要为以下对象创建一个Comparator对象:

    • 多重比较。提供几种不同的方式对事物进行排序。例如,您可能想按名称,ID,年龄,身高……对Person类进行排序。您将为每个这些类定义一个Comparator,以传递给sort()方法。
    • 系统类为您无法控制的提供比较方法。例如,您可以为字符串定义一个比较器,以按长度比较它们。
    • 策略模式要实现策略模式,在这种情况下,您需要将算法表示为可以作为参数传递,保存在数据结构等中的对象。

如果您的类对象具有自然排序顺序,则可能不需要compare()。


来自http://www.digizol.com/2008/07/java-sorting-comparator-vs-comparable.html的摘要

可比
对象可比对象能够将自己与另一个对象进行比较。

比较
器比较器对象能够比较两个不同的对象。该类不是在比较其实例,而是在比较其他一些类的实例。


用例上下文:

可比的界面

equals方法和==and != 运算符测试是否相等/ 相等,但没有提供测试相对值的方法
一些类(例如String和其他具有自然顺序的类)实现了Comparable<T>接口,该接口定义了一个compareTo()方法。如果要与或方法一起使用,则需要在类中
实现。Comparable<T>Collections.sort()Arrays.sort()

定义比较器对象

您可以创建Comparators来对任何类进行任意排序
例如,String该类定义了CASE_INSENSITIVE_ORDER比较器


两种方法之间的差异可以链接到以下概念:
有序集合

订购Collection时,这意味着您可以按特定(非随机)顺序(Hashtable不订购a)在集合中进行迭代。

具有自然顺序的 Collection 不仅是有序的,而且是排序的。定义自然顺序可能很困难!(如自然的String顺序)。


HaveAGuess评论中指出的另一个区别

  • Comparable 在实现中并且在界面中不可见,因此当您进行排序时,您实际上并不知道会发生什么。
  • Comparator 让您放心,订购将得到明确定义。

2
由于此答案是详尽无遗的,因此您可能想添加一些有关Comparable的信息:它在实现中,在界面中不可见,因此当您进行排序时,您实际上并不知道会发生什么。使用比较
器使

@HaveAGuess好点。我已将您的评论包含在答案中,以提高知名度。
VonC

对象具有自然顺序,自然顺序在这里意味着什么?字符串数据成员(例如,员工类中的姓名)是否具有自然顺序?
Narendra Jaggi

@NarendraJaggi参见en.wikipedia.org/wiki/Enumeration。便于枚举的命令。从某种意义上说,“自然”是指索引集上给定的良好排序提供了一种在给出部分枚举的情况下列出下一个元素的独特方法
VonC 2016年

2
@VedantKekan谢谢。我已经在此答案中恢复了2个链接。
VonC

16

compareTo()来自Comparable界面。

compare()来自Comparator界面。

两种方法都做同样的事情,但是每个接口使用的上下文略有不同。

可比接口用于强加于实现类的对象自然排序。该compareTo()方法称为自然比较法。该比较器接口用于强加于实现类的对象进行整体排序。有关更多信息,请参见确切何时使用每个界面的链接。


你能举一些例子吗?两种方法都给出相同的答案?

我不知道为什么“可比”用于自然排序?我们可以自定义它,不是吗?
c-

14

相似之处:
两者都是比较两个对象的自定义方式。
两者都返回一个int描述两个对象之间关系的描述。

区别: 该方法compare()是您必须实现Comparator接口的方法。它允许您将两个对象传递到方法中,并返回int描述它们之间关系的描述。

Comparator comp = new MyComparator();
int result = comp.compare(object1, object2);

该方法compareTo()是您必须实现Comparable接口的方法。它允许将一个对象与相似类型的对象进行比较。

String s = "hi";
int result = s.compareTo("bye");

简介:
基本上,它们是比较事物的两种不同方法。


9

这些方法不必给出相同的答案。这取决于您将其称为哪些对象/类。

如果您要实现自己的类,并且知道自己想在某个阶段进行比较,则可以让它们实现Comparable接口并相应地实现compareTo()方法。

如果您使用的API中的某些类未实现Comparable接口,但您仍要进行比较。即用于排序。您可以创建自己的实现Comparator接口的类,并在其compare()方法中实现逻辑。


3

可比接口包含一个名为的方法compareTo(obj),该方法仅接受一个参数,并将其与另一个实例或同一类的对象进行比较。

比较器接口包含一个名为的方法compare(obj1,obj2),该方法带有两个参数,并且它比较来自相同或不同类的两个对象的值。


3
compareTo(T object)

来自java.lang.Comparable接口,该接口实现了将该对象与另一个对象进行比较,以使此对象的负int值小于,等于等于0或大于另一个表示正值。这是比较方便的比较方法,但是必须在要比较的每个类中实现。

compare(T obj1, T obj2)

来自java.util.Comparator接口,该接口在单独的类中实现,该类对另一个类的对象进行比较,以使第一个对象的int值小于或等于0,等于或大于第二个对象的正值。当您无法使类实现compareTo()时,因为它不可修改,所以需要它。当您需要不同的对象而不是对象(例如,按名称或年龄)的比较方法时,也可以使用它。


3

使用Comparator,我们可以为一个类编写n个比较逻辑

例如

对于汽车课

我们可以有一个Comparator类来根据汽车型号进行比较。我们还可以有一个Comparator类来根据汽车型号年份进行比较。

车类

public class Car  {

    int modelNo;

    int modelYear;

    public int getModelNo() {
        return modelNo;
    }

    public void setModelNo(int modelNo) {
        this.modelNo = modelNo;
    }

    public int getModelYear() {
        return modelYear;
    }

    public void setModelYear(int modelYear) {
        this.modelYear = modelYear;
    }

}

基于型号No.1的比较器

public class CarModelNoCompartor implements Comparator<Car>{

    public int compare(Car o1, Car o2) {

        return o1.getModelNo() - o2.getModelNo();
    }

}

基于型号年份的比较器2

public class CarModelYearComparator implements Comparator<Car> {

    public int compare(Car o1, Car o2) {

        return o1.getModelYear() - o2.getModelYear();
    }

}

但这在Comparable接口的情况下是不可能的。

在Comparable接口的情况下,compareTo()方法中只能有一种逻辑


2

使用此方法的对象及其协作者之间的关系是不同的。

compareTo()Comparable接口的一种方法,因此用于将THIS实例与另一个实例进行比较。

compare()Comparator接口的一种方法,因此用于将另一个类的两个不同实例相互比较。

如果愿意,实现Comparable意味着可以轻松比较该类的实例。
实现Comparator方法是,实例适合比较(其他类的)不同对象。


2

主要区别在于接口的使用:

Comparable(具有compareTo())要求将对象进行比较(以便使用TreeMap或对列表进行排序)以实现该接口。但是,如果该类未实现Comparable并且由于它是3rd party库的一部分而无法更改它怎么办?然后,您必须实现一个比较器,使用起来不太方便。


2

compareTo()在一个对象上被调用,以将其与另一个对象进行比较。 compare()在某个对象上调用,以比较其他两个对象。

区别在于定义了进行实际比较的逻辑。


这不是我所说的绝妙答案,但我认为这不应该被否决。
Paul Tomblin,2009年

同意,我个人保留对错误或误导性答案的反对意见。这绝对是正确的。
约阿希姆·绍尔

那么那些打败我的“友好”人呢?这是我的第二个正确答案,因为有人错过了重点,因此被否决了。无论是无礼还是我的答案。生活是如此残酷
..-)

0

当您要对包含Object Foo的List进行排序时,Foo类必须实现Comparable接口,因为List的sort方法使用此方法。

当您要编写一个Util类来比较其他两个类时,可以实现Comparator类。


0

员工表
名称,DoB,薪水
Tomas,1982年2月10日,300
Daniel,1990年3月11日,400
Kwame,1998年2月10日,520

可比的界面允许您进行排序的对象如参照一个主要领域的员工列表-例如,你可以按名称排序或通过与工资的CompareTo)(方法

emp1.getName().compareTo(emp2.getName())

比较器接口提供了一种更灵活的接口来满足此类要求,该接口的唯一方法是compare()

public interface Comparator<Employee> {
 int compare(Employee obj1, Employee obj2);
}

样例代码

public class NameComparator implements Comparator<Employee> {

public int compare(Employee e1, Employee e2) {
     // some conditions here
        return e1.getName().compareTo(e2.getName()); // returns 1 since (T)omas > (D)an 
    return e1.getSalary().compareTo(e2.getSalary()); // returns -1 since 400 > 300
}

}


0

还有一点:

  • compareTo()来自Comparable接口,compare()也来自Comparator接口。
  • Comparable用于定义类中对象的默认顺序,同时Comparator用于定义要传递给方法的自定义顺序。

0

还有一个技术方面也应该强调。假设您需要从客户端类进行比较行为参数化,并且您想知道是否使用ComparableComparator用于这样的方法:

class Pokemon {
    int healthPoints;
    int attackDamage;
    public void battle (Comparable<Pokemon> comparable, Pokemon opponent) {
        if (comparable.compareTo(opponent) > 0) { //comparable needs to, but cannot, access this.healthPoints for example
            System.out.println("battle won");
        } else {
            System.out.println("battle lost");
        }
    }
}

comparable会是lambda或对象,并且无法comparable访问thisPokemon 的字段。(在lambda中,this指的是lambda范围内的外部类实例,如程序文本中所定义。)因此,这不可行,我们必须使用Comparator带有两个参数的a。


0

使用Comparable接口基于多个值(例如age,name,dept_name)进行排序...对于一个值,请使用Comparator接口


-2
Important Answar
String name;
int roll;

public int compare(Object obj1,Object obj2) { // For Comparator interface
    return obj1.compareTo(obj1);
}

public int compareTo(Object obj1) { // For Comparable Interface
    return obj1.compareTo(obj);
}

在此return obj1.compareTo(obj1)return obj1.compareTo(obj)声明中仅采用Object;不允许使用原语。例如

name.compareTo(obj1.getName()) // Correct Statement.

roll.compareTo(obj1.getRoll()) 
// Wrong Statement Compile Time Error Because roll 
// is not an Object Type, it is primitive type.

名称是String对象,因此可以正常工作。如果要排序学生的卷数,请使用以下代码。

public int compareTo(Object obj1) { // For Comparable Interface
    Student s = (Student) obj1;
    return rollno - s.getRollno();
}  

要么

public int compare(Object obj1,Object obj2) { // For Comparator interface
    Student s1 = (Student) obj1;
    Student s2 = (Student) obj2;
    return s1.getRollno() - s2.getRollno();
}  
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.