为什么 Java 类应该实现类似的功能?

为什么使用 JavaComparable?为什么有人要在类中实现 Comparable?在现实生活中,你需要实现什么样的例子来进行比较?

276796 次浏览

类实现 Comparable的事实意味着您可以从该类获取两个对象并对它们进行比较。有些类,比如某些集合(集合中的排序函数) ,保持对象的顺序依赖于它们的可比性(为了排序,你需要知道哪个对象是“最大的”等等)。

引自 javadoc;

这个接口强加了一个总计 对每个类的对象进行排序 实现它。这个命令是 被称为班级的自然 订购,和类的比较 方法被称为其自然 比较法。

对象的列表(和数组) 实现这个接口可以排序 自动通过 Collections.sort (和 实现 此接口可用作 排序的映射或作为 排序集,而不需要 指定一个比较器。

编辑: . . 并使重要的一点大胆。

例如,当您希望有一个排序的集合或 地图

可比定义自然排序。这意味着,当一个对象应该被认为是“小于”或“大于”时,您就是在定义它。

假设你有一堆整数,你想对它们进行排序。很简单,把它们分类收集,对吧?

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;
}

现在,对它们进行排序的最简单方法是通过实现 Compaable,使用自然排序来定义它们,这意味着有一种标准的方法来定义这些对象的排序:

public class District implements Comparable<District>{
String zipcode;
Double populationDensity;
public int compareTo(District other)
{
return populationDensity.compareTo(other.populationDensity);
}
}

注意,您可以通过定义一个比较器来完成相同的事情。区别在于比较器定义了排序逻辑 在物体之外。也许在一个单独的过程中,我需要按照邮政编码对相同的对象进行排序——在这种情况下,排序不一定是对象的属性,或者不同于对象的自然排序。可以使用外部比较器定义整数的自定义顺序,例如按字母顺序对整数进行排序。

基本上,排序逻辑必须存在于某个地方。这可以是-

  • 在对象本身中,如果它是自然可比较的(扩展可比较的-例如整数)

  • 由外部比较器提供,如上例所示。

下面是一个真实的例子。请注意,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;
}
}

待会儿。

/**
* 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);
}

上面的大多数示例展示了如何在 compareTo 函数中重用现有的可比对象。如果你想实现你自己的 compareTo 当你想比较同类中的两个对象时,比如一个 AirlineTicket 对象,你想按价格排序(越少排在第一位) ,然后是中途停留的次数(同样,越少排在第一位) ,你可以这样做:

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;
}
}

实现多字段比较的一个简单方法是使用 番石榴比较链-然后您可以说

   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);
}
}

可比对象用于比较类的实例。我们可以通过多种方式比较实例,这就是为什么我们需要实现一个方法 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
*/


}
}

下面是一个在 Java 中如何使用可比性的好例子:

Http://www.onjava.com/pub/a/onjava/2003/03/12/java_comp.html?page=2

实现 Comparable接口时,需要实现方法 compareTo()。您需要它来比较对象,以便使用,例如,ArrayList类的排序方法。您需要一种方法来比较您的对象,以便能够对它们进行排序。因此,您需要在类中使用一个自定义的 compareTo()方法,这样就可以将它与 ArrayList排序方法一起使用。compareTo()方法返回 -1,0,1。

我刚刚读了 Java Head 2.0中的一个相关章节,我还在学习中。

好吧,但是为什么不定义一个不实现可比接口的 compareTo()方法呢。 例如,由其 nametemperature定义的类 City

public int compareTo(City theOther)
{
if (this.temperature < theOther.temperature)
return -1;
else if (this.temperature > theOther.temperature)
return 1;
else
return 0;
}