Java中类的等价关系和自然排序

时间:2014-10-22 20:03:16

标签: java sorting collections

我非常了解Comparable和Comparator接口之间的区别,以及 就像他们所强加的那样。

此外,我清楚为什么compareTo必须与equals方法一致。 来自Oracle docs

  

强烈建议(尽管不是必需的)自然排序是一致的       与平等。这是因为排序集(和排序映射)没有显式       比较器在与元素(或键)一起使用时表现得“奇怪”       其自然顺序与equals不一致。特别是这样的       有序集(或有序映射)违反集合(或映射)的一般合同,       这是用等于方法定义的。

     

例如,如果添加两个键ab,那么       (!a.equals(b) && a.compareTo(b) == 0)到不使用的排序集       显式比较器,第二个add操作返回false(和大小       排序集不会增加)因为a和b等价于       排序集的观点。

但是,我无法对段落(下文)清楚自己,

  

对于数学倾向,定义自然顺序的关系       给定的C类是:

    {(x, y) such that x.compareTo(y) <= 0}.
     

此总订单的是:

    {(x, y) such that x.compareTo(y) == 0}.
     

紧跟compareTo的合同后,该商为商       C上的等价关系,自然排序是C上的总顺序。       当我们说一个类的自然顺序与equals 一致时,我们的意思是       自然排序的商是定义的等价关系       通过班级的equals(Object)方法:

    {(x, y) such that x.equals(y)}.  

作者试图在这里提出什么建议?有人可以用一个简单的例子来解释。

3 个答案:

答案 0 :(得分:4)

基本上它是说与equals 一致意味着xy的{​​{1}},x.compareTo(y) == 0}对的集合与truex的{​​{1}},y)对的集合相同。

这与第一段中使用的与equals 一致的常识理解有所不同。它只是以正式的代数方式表达定义。我确定有人认为将这些内容添加到文档会很有趣,但我不确定它对程序员有什么实际用处。

答案 1 :(得分:0)

让我们说你创造了这个愚蠢的阶级

public class A implements Comparable<A> {
  private int value;

  public A(int value){
    this.value = value }

  public boolean equals(Object obj){ 
     if (obj instanceof A)
        return this.value = ((A)obj).value;
     else return false;
  }

  public int compareTo(A another){
     return 0;
  }
}

然后创建两个实例:

A a1 = new A(3);
A a2 = new A(4);
SortedSet<A> set = new TreeSet<A>();
set.add(a1);
set.add(a2);

SortedSet接受a1但它不接受a2,因为a1.equals(a2)== false但是a2.compareTo(a2)== 0; 请记住,在定义集合中,所有元素彼此不同(它就像集合的数学概念)。

答案 2 :(得分:0)

这都是数学! (x,y)表示&#34; x与y&#34;

有关

等价关系是对元素集合(在本例中为C类的实例)的反射,对称和过渡的关系。

反思意味着:每个元素都与自身相关 对称意味着:如果a与b有关,那么b与a有关 过渡意味着:如果a与b有关,b与c有关,则与c有关。

所以x.compareTo(y)== 0的商关系因此是C的每个实例c的等价关系:c.compareTo(c)应该为零,对于来自C的每个实例c1,c2 :如果c1.comparTo(c2)== 0则c2.compareTo(c1)也应该为零。对于所有c1,c2,c3,其中c1.compareTo(c2)为零,c2.compareTo(c3)为零,则c1.compareTo(c3)也应为零。

总顺序是一个传递的关系(参见上文),反对称(再次见上文,但现在反转为反对)和总数 因此,compareTo应反映总订单: 如果a.compareTo(b)是&lt; = 0并且b.compareTo(c)&lt; = 0那么a.compareTo(c)必须是&lt; = 0 如果a.compareTo(b)是&lt; = 0那么b.compareTo(a)必须是&gt; = 0

total表示a.compareTo(b)&lt; = 0或者b.compareTo(a)&lt; = 0,总数是指任何元素都可以与另一个元素进行比较,因此所有元素都可以被排序,因此订购总计

商是来自a.compareTo(b)&lt; = 0和b.compareTo(a)&lt; = 0因此a.compareTo(b)== 0

我希望这比原来的更具说明性......