3

Below is a block of code that results in exception as indicated,

Code :

Collections.sort( arrayList, new Comparator() 
{
    public int compare( Object o1, Object o2 )
    {
        TypeAdapterSort tas1 = ( TypeAdapterSort ) o1;
        TypeAdapterSort tas2 = ( TypeAdapterSort ) o2;
        if ( tas1.order < tas2.order )
            return -1;
        else
            return 1;
    }
} );

Exception :

java.lang.IllegalArgumentException: Comparison method violates its general contract!
                at java.util.TimSort.mergeLo(TimSort.java:747)
                at java.util.TimSort.mergeAt(TimSort.java:483)
                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)

When I run the same code as a standalone program, the issue never occurs. What is the issue with the comparator here? Is there a way to reproduce the issue in a standalone code?

This issue occurs only on Java 1.7 as there has been change in the implementation on Arrays.sort & Collections.sort. How to change the above code to avoid the issue?. Also, how to reproduce this issue in a standalone code?

Hermann Hans
  • 1,798
  • 1
  • 13
  • 24
Mohan
  • 155
  • 1
  • 4
  • 10
  • 1
    if order is of type `Integer` you could return `tas1.order.compareTo(tas2.order)` – Marco Forberg Apr 18 '13 at 09:03
  • what do you mean by 'standalone program'? Or rather, what other option of running the code you are referring to? – Grzegorz Oledzki Apr 18 '13 at 09:47
  • possible duplicate of ["Comparison method violates its general contract!"](http://stackoverflow.com/questions/8327514/comparison-method-violates-its-general-contract) – Philipp Reichart Apr 18 '13 at 10:33
  • You already asked this question: [compare method violates its general contract exception java 7](http://stackoverflow.com/questions/15897892/compare-method-violates-its-general-contract-exception-java-7) – Duncan Jones Apr 19 '13 at 07:51

1 Answers1

3

You need to return 0 on equal objects.

        if ( tas1.order < tas2.order ){
            return -1;
        } else if ( tas1.order == tas2.order ){
            return 0;
        } else {
            return 1;
        }

You can read here more

Community
  • 1
  • 1
BobTheBuilder
  • 18,858
  • 6
  • 40
  • 61
  • But, why is the issue not reproduced when run as a standalone program where the value of intance variable order is maintained the same? – Mohan Apr 18 '13 at 09:01
  • compare must be transitive. Your code isn't. So instead of working incorrectly, it states to you that your code is buggy. I think it is a very good behavior. – BobTheBuilder Apr 18 '13 at 09:04
  • @baraky You might expect to write `tas1.order == tas2.order`, you surely missed the double "=" instead of ... assignment ;) – Mik378 Apr 18 '13 at 09:19