java中String比较的Transitivity属性

时间:2015-05-12 12:59:39

标签: java string comparator compareto timsort

看一下这段代码

   class StringComparator implements Comparator<String> {

     @Override
     public int compare(String a, String b) {
         if (a.length() == b.length()) {
             return b.compareTo(a);
         } else {
             String ab = a + b;
             String ba = b + a;
             return ba.compareTo(ab);
         }
     }
 }

ba.compareTo(ab)有效,但ab.compareTo(ba)失败。它引发违反比较器合同的IllegalArgumentException。我相信它是由于传递性质不满足的事实。有人可以解释一下Java在字符串的情况下如何使用transitivity属性吗?这与Timsort的工作原理有什么关系吗?

编辑:这是我在Leetcode在线评判中得到的错误

Runtime Error Message:
                Line 32: java.lang.IllegalArgumentException: Comparison method violates its general contract!




              Last executed input:
                [7286,155,351,6059,9686,2668,9551,5410,7182,170,3746,3095,8139,2587,2351,2341,2038,3956,6034,4071,9473,281,9306,8746,7954,8937,7855,3938,9737,2455,4344,2986,8968,1072,2442,7191,9106,4236,2768,5214,7541,329,7530,9068,9644,3539,5177,5332,2065,8245,7494,8454,604,4632,1745,301,3412,1569,8637,7840,7752,9536,1023,4841,1286,6489,8459,2725,8021,5026,7058,4540,9892,5344,1205,4363,959,9729,9225,9733,8417,9873,3721,1434,5136,6111,6189,780,4741,2670,2457,5424,1040,3746,1229,8568,3636,1546,2553,575]

再次,当我使用ba.compareTo(ab)时,我不会收到此错误。我

2 个答案:

答案 0 :(得分:1)

是的,如果comparea的长度不同,则b似乎不会尊重传递属性。

这是Comparator.compare(a,b) contract,请参阅关于及物性的粗体部分:

  

比较其订单的两个参数。返回一个负整数,   零或正整数,因为第一个参数小于,等于   到或大于第二个。在前面的描述中,   符号sgn(表达式)表示数学符号函数,   它被定义为根据是否返回-1,0或1中的一个   表达式的值为负,零或正。

     

实现者必须确保sgn(compare(x,y))== -sgn(比较(y,   x))所有x和y。 (这意味着compare(x,y)必须抛出一个   异常,当且仅当compare(y,x)抛出异常时。)

     

实现者还必须确保关系是可传递的:   ((compare(x,y)&gt; 0)&amp;&amp;(compare(y,z)&gt; 0))暗示比较(x,z)> 0

     

最后,实现者必须确保compare(x,y)== 0暗示   所有z的sgn(compare(x,z))== sgn(compare(y,z))。

     

通常情况如此,但并非严格要求(比较(x,   y)== 0)==(x.equals(y))。一般来说,任何比较器   违反这一条件应清楚地表明这一事实。该   建议的语言是“注意:这个比较器强制执行排序   与平等不一致。“

更新

只是添加一个有趣的附注,你可以将Tim sort作为Collections.sort()等应用的排序算法,对于较小的数组(在硬编码阈值下的大小),简单的合并而是执行排序。选择在sort方法的开头进行,有关详细信息,请参阅openJDK源。

答案 1 :(得分:0)

假设我们有三个数字,字符串格式为a,b和c,a | b | c是可以获得的最大结果。

然后我们知道(a | b) > (b | a)(b | c) > (c | b)

假设(c | a) > (a | c)(没有及物性),那么我们有:

(c | a | b) > (a | c | b) > (a | b | c)。这种矛盾a | b | c是最大的。