【发布时间】:2018-03-29 18:26:26
【问题描述】:
我的理解是 Comparator 可以比较来自不同类的多个对象,而 Comparable 只能将一个对象与同一类中的另一个实例进行比较。
比较 (object1) 比较(object1,object2)
上面的解释是真的吗??
【问题讨论】:
-
比较器 - 两个参数的类型必须相同
我的理解是 Comparator 可以比较来自不同类的多个对象,而 Comparable 只能将一个对象与同一类中的另一个实例进行比较。
比较 (object1) 比较(object1,object2)
上面的解释是真的吗??
【问题讨论】:
不是。Comparable 和 Comparator 是通用接口,允许比较泛型中定义的类型的实例(包括子类)。
它们之间的主要区别在于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<String>:
strings.sort(new StringLengthComparator());
或者不使用 lambda 创建任何类:
strings.sort((o1,o2)->Integer.compare(o1.length(), o2.length()));
应使用Comparator 代替Comparable 的示例:
假设您有一个代表银行帐户的 Account 类。
从功能上讲,您没有对它们进行排序的自然顺序,而是根据客户的需要有多个订单。
让类实现Comparable 是没有意义的。但是创建不同的Comparator<Account> 会。
只能使用Comparator的情况:
如果要为无法更改源代码的类(JDK 类或第三方类)的实例定义顺序,Comparator 是遵循的方式。
【讨论】:
此答案基于从 Intertech Training 的 Complete Java SE 8 Developer Bootcamp 课程中提取的信息。据他们说
Comparable 界面显示“这个特定对象将 与另一个对象相比”,而 Comparator 有点像 这个第三方“给我任何两个对象,我会告诉你如何 他们是订购的”。
Comparable和Comparator都位于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接口。
比较器在比较异构集合的元素和我们没有源的第三方类时很有用。
【讨论】:
我认为,当我们想通过多个属性自然地比较用户定义的类时,最好使用 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 等。
【讨论】: