4

Possible Duplicate:
why does my compare method throw exception — Comparison method violates its general contract!

I've this code:

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

Sometimes it thrown this exception:

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)

Why ?

1) how can I avoid it? 2) how can i catch this exception ?

Thanks in advance.

Community
  • 1
  • 1
famedoro
  • 1,223
  • 2
  • 17
  • 41
  • 1
    The very first google result of your exact error gives multiple solutions as well as the cause. – Charles Apr 19 '12 at 18:06

1 Answers1

6

If you have two elements when are equal a and b you will get compare(a, b) == -1 and compare(b, a) == -1 which doesn't make any sense.

You can simplify the code with and make it more efficient with

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;
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Thanks for your response, but I don't understand a thing: when a and b are equals doesn't compare(a, b) is equal to 0 ? AS explained in http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Comparator.html#compare%28java.lang.Object,%20java.lang.Object%29 – famedoro Apr 19 '12 at 18:17
  • 1
    They should be, but you never return 0. BTW: its best to use Javadoc from Java 7 as Java 6 will be EOL soon. ;) – Peter Lawrey Apr 19 '12 at 18:23
  • Thanks, just a last question: how can i catch this exception using try/catch statement? – famedoro Apr 19 '12 at 18:26
  • 3
    Do you mean `try { } catch(IllegalArguementException e) { e.printStackTrace(); }` ? Given it a programming error, its not something you can fix at runtime. – Peter Lawrey Apr 19 '12 at 18:30