2016-06-28 78 views
2

我知道这似乎是一个微不足道的问题(我毫不怀疑所有'聪明人'会来标记它为重复),但我没有找到足够的解释我的问题。难道这让我很难理解这个简单的主题吗?如何在实现“可比较”时定义排序顺序?

我理解其背后Comparable接口以及它是如何工作的基础知识,但我有一个真正的困难已了解如何确定的排序ORDER

例如 - 我有一个非常简单的Fruit类:

public class Fruit implements Comparable<Fruit> { 
private String fruitName; 
private String fruitDesc; 
private int quantity; 

public Fruit(String fruitName, String fruitDesc, int quantity) { 
    this.fruitName = fruitName; 
    this.fruitDesc = fruitDesc; 
    this.quantity = quantity; 
} 

public String getFruitName() { 
    return fruitName; 
} 
public void setFruitName(String fruitName) { 
    this.fruitName = fruitName; 
} 
public String getFruitDesc() { 
    return fruitDesc; 
} 
public void setFruitDesc(String fruitDesc) { 
    this.fruitDesc = fruitDesc; 
} 
public int getQuantity() { 
    return quantity; 
} 
public void setQuantity(int quantity) { 
    this.quantity = quantity; 
} 

public int compareTo(Fruit compareFruit) { 
    //ascending order 
    return this.quantity - ((Fruit) compareFruit).getQuantity(); 
} 

为什么声明compareTo像上面会按升序进行排序,并在声明它的时候正好相反:

return ((Fruit) compareFruit).getQuantity() - this.quantity; 

它将按降序排列?

+0

你是什么意思,“你怎么确定他们之间?”?你的意思是如何订购相同数量的水果?这基本上取决于所使用的排序算法。但是你不应该对这些元素的顺序做任何假设,因为它可能会被忽视。如果您依赖一个确切而稳定的订单,则需要确保您的班级的所有属性都是按排序顺序考虑的。 – dpr

+0

不知道我是否正确理解你的问题 - 排序顺序只是由'compareTo'返回的整数符号决定的。顺便说一下,不要通过getter和直接属性访问混合访问属性。 –

+0

当您交换认为大于或小于的顺序时,您将从升序切换到降序。 –

回答

2

Javadoc

比较与指定对象此对象为顺序。返回 负整数,零或正整数,因为此对象比指定对象的 小,等于或大于此值。实现者 必须为所有x和 确保sgn(x.compareTo(y))== -sgn(y.compareTo(x))。 (这意味着则x.compareTo(Y)当且仅当 y.compareTo(X)抛出异常必须抛出异常。)

实现类还必须确保关系是可传递: (则x.compareTo(Y) > 0 & & y.compareTo(z)> 0)意味着x.compareTo(z)> 0。

最后,对于所有z,实现者必须确保x.compareTo(y)== 0意味着 sgn(x.compareTo(z))== sgn(y.compareTo(z))。

强烈建议,但不是严格要求 (x.compareTo(y)== 0)==(x.equals(y))。一般而言,任何实现了Comparable接口并且违反 条件的类 都应该清楚地表明这一事实。推荐的语言是“注: 这个类的自然排序与equals不一致。”

在前面的描述中,符号sgn(表达式)指定数学符号函数,该函数被定义为根据表达式的值是负数,零还是正数来返回 -1,0或1中的一个。

1

sort方法按其定义按升序进行排序。

根据 的元素自然排序将指定列表按升序排序。

compareTo方法是就在你的第一例子中,错误的在第二,根据:

比较与指定对象此对象为顺序。返回 负整数,零或正整数,因为此对象比指定对象的 小,等于或大于此值。

+0

为什么它错了?我检查了它,它工作完美。 那么,当我在对象之间进行交换时,返回的(int)号码现在相反,所以位置顺序? – Nimrod

+0

@Nimrod,这是错误的,因为它不尊重来自“Comparable”的方法定义的合同。如果您需要反向排序,请使用其他方式,例如'Collections.reverseOrder()':https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#reverseOrder()。 – Berger

+0

对不起,但我仍然不明白.. 'Collections'与列表相关,而我想使用一个数组。你能举一个例子还是更具体? – Nimrod

0

从我的理解,如果方法返回一个负值(值小于0),第一个对象出现在排序列表中的第二个对象之前。如果它返回一个正值(值大于0),则第一个对象位于排序列表中的第二个对象之后。如果它返回0,那么这两个对象是相等的。

第一个对象是指您的示例中由this关键字引用的对象,第二个对象是指传入compareTo方法的对象。

0

从Java API:

比较与指定对象这个对象的顺序。返回负整数,零或正整数,因为此对象小于,等于或大于指定的对象。

链接:https://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html

compareTo()方法返回一个整数,它告诉分拣机实例之间的相对位置,使得if (a.compareTo(b) > 0),然后a被认为是“大”,因此应该出现在排序的列表b后。同样if (a.compareTo(b) < 0)a被认为是“较小”。

因此,如果你想按升序排列,你应该compareTo()执行引用thiscompareObject之前,即this.value - compareObject.value;

坚持简而言之: a.compareTo(b) > 0基本意思是“一个大于b”。同样a.compareTo(b) < 0意味着“a小于b”。

0

compareTo方法确定而不是确定排序操作的顺序(升序与降序)。

定义排序操作的代码确定顺序。排序操作会重复调用compareTo,对于要排序的集合中的每个对象至少调用一次。排序操作的其余代码如何跟踪调用compareTo代码的结果,确定结果是升序还是降序。例如,Collections.sort排序操作总是按升序排序。该库中的代码将调用每个对象的方法compateTo