我知道这些接口用于Collection中的排序对象。但我怀疑这些的真正区别。我读到的一个事实是,当你想要将两个对象与当前对象(这个)进行比较时,使用可比性。
但我的问题是甚至比较我们比较相同的对象类型知道。
这里有什么不同。我很迷惑。 假设以下示例
class Person implements Comparable<Person> {
private String firstName;
private String lastName;
private int age;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int compareTo(Person anotherPerson){
int anotherPersonAge =anotherPerson.getAge();
return this.age - anotherPersonAge;
}
}
如果我使用比较器,我会有一个类实现比较器,而不是this.age,它有person.age。那么这里有什么不同呢?
public class LastNameComparator implements Comparator<Person> {
public int compare(Person person, Person anotherPerson) {
int age1 = person.getAge();
int age2 = anotherPerson.getAge();
return age1 - age2;
}
}
我不知道Collections.sort使用的内部逻辑。如果是这样的话,请证明上述观点是合理的。
另外我认为不需要返回-1,1或0。以上实施也有效吗?我遇到的一个问题是,如果我们返回1,列表如何按照升序或降序对项目进行排序?我认为差异考虑并根据差异对它们进行排序。
答案 0 :(得分:1)
此接口对每个类的对象施加总排序 实现它。这种排序称为类 自然排序,类的compareTo方法称为 它的自然比较方法。
比较函数,对某些函数施加总排序 对象的集合。可以将比较器传递给排序方法 (例如Collections.sort或Arrays.sort)允许精确控制 超过排序顺序。比较器也可用于控制订单 某些数据结构(如排序集或排序映射)或 为没有的对象集合提供排序 自然排序。
Comparable
对象可以通过将自身与另一个对象(自然排序)进行比较来确定其顺序,而Comparator
是一个知道如何比较两个对象并确定其特定顺序的对象。这里的不同之处在于谁负责比较。
自然排序使用compareTo
强加定义的顺序,但如果您想要更改该顺序,或者更糟糕的是,没有定义的比较逻辑,该怎么办?这里是Comparator
派上用场的地方,因为您可以根据不同的比较对集合进行排序,这些比较可以通过发布新的Comparator
动态切换,而不是一些令人讨厌的逻辑,您应该告诉{{1}对象“嘿,现在你按照名字而不是年龄订购”。
关于比较结果之间的差异,检查每个对象。例如,请年龄为Comparable
,10
和15
的三个人。 20
与15
相比时返回1,但与10
相比,返回-1
,定义了三个人的顺序。
选择适合您需求的方法。如果您的比较逻辑稳定且将来不会更改,您可能希望拥有20
个对象,但是您是否需要根据Comparable
s的不同标准对集合进行排序
答案 1 :(得分:0)
快速扫描java.util.Collections javadocs提供了这个:
public static void sort(列表列表) - 根据元素的自然顺序,将指定列表按升序排序。 列表中的所有元素都必须实现Comparable接口。此外,列表中的所有元素必须是可相互比较的(即,e1.compareTo(e2)不得对列表中的任何元素e1和e2抛出ClassCastException。)
public static void sort(列表列表, 比较者c) - 根据指定比较器引发的顺序对指定列表进行排序。 列表中的所有元素必须使用指定的比较器进行相互比较(即,c.compare(e1,e2)不得为列表中的任何元素e1和e2抛出ClassCastException。) p>
可以推断,sort(List list)
然后使用Comparable接口,sort(List list, Comparator c)
使用比较器。
要回答你的最后一个问题,以你描述的方式使用这两种方法没有区别......这两种方法的目的是让你可以用不同的方式比较对象,而不是以相同的方式使用不同的实现。
答案 2 :(得分:0)
以这种方式考虑......你有Class IntegerWrapper ,它有一个整数,你在类中实现了 Comparable 。因此,当使用Collection.sort对它们进行排序时......它将按升序为您提供对象...
但是当您想要更改此订单并希望降序订单时,您必须实施比较器以按所需顺序对其进行排序...
答案 3 :(得分:0)
在Java中,类型总是只能实现一次接口,就是你不能说
public class Foo implements Comparable<Foo>, Comparable<String> {}
这意味着Foo
的实例将始终以某种方式排序 - 您不能让排序在某个上下文中以某种方式表现,而在另一种上下文中则不同。
另一方面,Comparator
与它可以排序的实例无关。对于单个类型,您可以拥有尽可能多的Comparator
个(而不是一个Comparable
)。如果您需要某种排序,只需创建一个新的Comparator
即可。
编写一个对不同类型的实例进行排序的Comparator
也很容易 - 这对Comparable
很难处理,因为所有涉及的实例都必须彼此了解:任何实例都可以获得任何其他实例instance作为compareTo()
中的参数,它们必须实现一些通用接口等。
答案 4 :(得分:0)
当有人使用Comparable接口时,我总是很害怕,因为它几乎总是错误的选择。 Comparable用于定义自然顺序而不是用于排序。 Java知道必须满足的equals-hashcode契约。大多数开发人员都知道。但还有一个重要的合同:平等可比的合同。
这意味着:
a.equals(b)&lt; ==&gt; a.compareTo(b)== 0
在您的示例中,您不能在一个TreeSet中拥有两个具有相同年龄的不同人。