为什么要使用Java的Comparable
接口?为什么需要在类中实现Comparable
接口?能否给出一个实际场景的例子说明何时需要实现Comparable接口?
为什么要使用Java的Comparable
接口?为什么需要在类中实现Comparable
接口?能否给出一个实际场景的例子说明何时需要实现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);
}
last
? - Anirban Nag 'tintinmj'Comparable
接口只是让其他 Java 方法,而不仅仅是用户,可以比较两个对象吗?否则,如果没有它,您可以定义并使用一个 compareTo
方法,我就看不出实现 Comparable
的意义了。 - user3932000Comparable 定义了一种自然排序方式。这意味着当你需要定义一个对象比另一个对象“小”或“大”时,就可以使用它。
假设你有一堆整数,想要将它们排序。那很容易,只需将它们放入已排序的集合中即可,对吧?
TreeSet<Integer> m = new TreeSet<Integer>();
m.add(1);
m.add(3);
m.add(2);
for (Integer i : m)
... // values will be sorted
但现在假设我有一些自定义对象,在这些对象中排序对我来说是有意义的,但未定义。例如,我有一些数据,它代表了区域邮政编码和人口密度,我想按密度对它们进行排序:
public class District {
String zipcode;
Double populationDensity;
}
现在最简单的排序方式是通过实现Comparable接口并定义对象的自然顺序,这意味着存在一种标准的方式来定义这些对象的排序。
public class District implements Comparable<District>{
String zipcode;
Double populationDensity;
public int compareTo(District other)
{
return populationDensity.compareTo(other.populationDensity);
}
}
请注意,您可以通过定义比较器来实现等效的功能。不同之处在于比较器将排序逻辑定义为对象外部的内容。也许在另一个过程中,我需要按邮政编码对相同的对象进行排序 - 在这种情况下,排序并不一定是对象的属性,或者与对象的自然排序不同。例如,您可以使用外部比较器按字母顺序对整数进行自定义排序。TreeSet<Integer>
而不是TreeMap<Integer>
,因为后者不存在,TreeMaps始终是<Key,Value>
对。顺便说一句,假设的TreeMap<District, Object>
只有在District实现了Comparable接口时才能工作,对吧?我还在努力理解这个。 - phil294摘自javadoc:
该接口在实现它的每个类的对象上强加了一个完全有序的排序。此排序被称为类的自然排序,而类的compareTo方法被称为其自然比较方法。
实现此接口的对象的列表(和数组)可以通过Collections.sort(和Arrays.sort)自动排序。 实现此接口的对象可以用作排序映射中的键或排序集合中的元素,无需指定比较器。
编辑:..并将重要的部分加粗。
如果一个类实现了Comparable
接口,那么你可以拿这个类的两个对象进行比较。某些类,例如一些集合(集合中的排序函数)需要保持对象的顺序,因此它们依赖于这些对象是可比较的(为了排序,你需要知道哪个对象最大等等)。
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;
}
}
Cost
是否有一个名为AirlineTicket
的属性cost
?对于属性stopovers
(在这两个类中)也是如此吗?这非常奇怪... Cost
的实现是什么? - Stéphane Millien实现多字段比较的简单方法是使用Guava's ComparisonChain- 然后你可以说
public int compareTo(Foo that) {
return ComparisonChain.start()
.compare(lastName, that.lastName)
.compare(firstName, that.firstName)
.compare(zipCode, that.zipCode)
.result();
}
替代
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);
}
}
Comparable被用于比较类的实例。我们可以通过许多方式来比较实例,因此需要实现一个compareTo
方法以了解我们想要如何(属性)比较实例。
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
*/
}
}
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
*/
}
}
好的,但为什么不直接定义一个没有实现comparable接口的compareTo()
方法呢?例如,一个由其name
和temperature
定义的City
类。
public int compareTo(City theOther)
{
if (this.temperature < theOther.temperature)
return -1;
else if (this.temperature > theOther.temperature)
return 1;
else
return 0;
}
Comparable
接口时,需要实现compareTo()
方法。这样才能比较对象,例如使用ArrayList
类的排序方法。你需要一种比较对象的方式来对它们进行排序。所以,你需要在你的类中添加自定义的compareTo()
方法,这样就能够将其与ArrayList
的排序方法一起使用。compareTo()
方法返回-1、0、1。