比较方法抛出异常:比较方法违反了它的通用契约。

4
可能有重复问题:
为什么我的比较方法会抛出异常——比较方法违反了其一般契约!

我有这段代码:

class TimeComparatorTipo0 implements Comparator {
@Override
public int compare(Object a, Object b) {
     String Time1   = ((DataImportedTipo0) a).ora;
     Long   VolTot1 = Long.parseLong(((DataImportedTipo0) a).volume_totale);

     String Time2   = ((DataImportedTipo0) b).ora;
     Long   VolTot2 = Long.parseLong(((DataImportedTipo0) b).volume_totale);

    if (Time1.equals(Time2))
    {          
       if ( VolTot1.compareTo(VolTot2) > 0)
         return 1;
       else
         return -1;         
    }
    else
      return Time1.compareTo(Time2);
     }
};

有时候会抛出这个异常:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:868)
at java.util.TimSort.mergeAt(TimSort.java:485)
at java.util.TimSort.mergeForceCollapse(TimSort.java:426)
at java.util.TimSort.sort(TimSort.java:223)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)
at ManageUrl.DownloadUrl.StartThreadDowloadTipo0(DownloadUrl.java:893)
at ManageUrl.DownloadUpdateWorkflow$ConsumerTipo0.run(DownloadUpdateWorkflow.java:278)

为什么?

1)我该如何避免它? 2)我该如何捕获此异常?

提前致谢。


1
你的确切错误的第一个谷歌搜索结果提供了多个解决方案以及原因。 - Charles
1个回答

6
如果您有两个相等的元素ab,那么您将得到compare(a, b) == -1compare(b, a) == -1,这毫无意义。
您可以通过以下方式简化代码并使其更加高效:
class TimeComparatorTipo0 implements Comparator<DataImportedTipo0> {
@Override
public int compare(DataImportedTipo0 a, DataImportedTipo0 b) {
    String Time1 = a.ora, Time2 = b.ora;

    int cmp = Time1.compareTo(Time2);
    if (cmp == 0) {
       // avoid expensive operations.
       Long VolTot1 = Long.parseLong(a.volume_totale);
       Long VolTot2 = Long.parseLong(b.volume_totale);
       cmp = VolTot1.compareTo(VolTot2);
    }
    return cmp;

谢谢您的回复,但我一点也不明白:当a和b相等时,compare(a,b)不等于0吗?正如http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Comparator.html#compare%28java.lang.Object,%20java.lang.Object%29所解释的那样。 - famedoro
1
它们应该是这样的,但你永远不会返回0。顺便说一句:最好使用Java 7的Javadoc,因为Java 6很快就要EOL了。;) - Peter Lawrey
谢谢,最后一个问题:我如何使用try/catch语句捕获这个异常? - famedoro
3
你是指 try { } catch(IllegalArguementException e) { e.printStackTrace(); } 吗?由于这是一个编程错误,它不是你可以在运行时修复的。 - Peter Lawrey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接