This discussion is archived
12 Replies Latest reply: Apr 23, 2013 3:48 PM by EJP RSS

java.lang.IllegalArgumentException: Comparison method violates general.....

1004808 Newbie
Currently Being Moderated
Below code throws java.lang.IllegalArgumentException: Comparison method violates its general contract!,

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

class TypeAdapterSort {
int order;
}

I am not sure with what data in arraylist the above code throws the exception, please me know the data that needs to be populated in arraylist so that the exception occurs.
  • 1. Re: java.lang.IllegalArgumentException: Comparison method violates general.....
    Kayaman Guru
    Currently Being Moderated
    The method needs to return 0 for equal objects, or -1/1 for smaller/bigger. Your method doesn't return 0 in any case.
  • 2. Re: java.lang.IllegalArgumentException: Comparison method violates general.....
    1004808 Newbie
    Currently Being Moderated
    Even then, when i run the above code with a smaller dataset like an arraylist with values 1, 2, 3, 4, 5 it executes with no exceptions, it is only under certain conditions it throws exceptions.

    As I am not sure on the data that causes this issue, what elements should i populate in the arraylist above so that the exception is thrown?.
  • 3. Re: java.lang.IllegalArgumentException: Comparison method violates general.....
    gimbal2 Guru
    Currently Being Moderated
    1001805 wrote:
    Even then, when i run the above code with a smaller dataset like an arraylist with values 1, 2, 3, 4, 5 it executes with no exceptions, it is only under certain conditions it throws exceptions.
    So apparently whatever logic is in there that checks it can only properly do so when the list has sufficient values in it
    As I am not sure on the data that causes this issue, what elements should i populate in the arraylist above so that the exception is thrown?.
    You'd have to check the source code. But the real fix is to just follow the contract as documented in the javadocs.
  • 4. Re: java.lang.IllegalArgumentException: Comparison method violates general.....
    1004808 Newbie
    Currently Being Moderated
    Yes, following the contract will avoid the exception. But is exception not thrown with a smaller dataset of arraylist with 1,2,3,4,5 as it's elemensts in the above code.

    Is there i specific limitation on the size of arraylist and the manner in which it needs to contain the elements for the exception to be thrown?
  • 5. Re: java.lang.IllegalArgumentException: Comparison method violates general.....
    sabre150 Expert
    Currently Being Moderated
    I don't see how that exception can be thrown since unless the comparator code is analysed at runtime nothing will know that zero is never returned.
  • 6. Re: java.lang.IllegalArgumentException: Comparison method violates general.....
    1004808 Newbie
    Currently Being Moderated
    Yes, very true. What pattern of data (equal elements, ascending, descending etc) can cause this comparator throw the exception java.lang.IllegalArgumentException while passing it as a parameter to Collections.sort?.

    I need this pattern of data or any sample data that fails this code. Any sample data with few elements that make the code fail will be of great help!!.

    Also, this exception can be thrown only if the size of the collection to be sorted is greater that 32 as per the JDK.

    JDK 1.7 uses binarysort to sort the elements if the collections size < 32 and does not throw the exception in this case.

    If the collection size is > 32 it uses Tim sort and also throws the exception if the comparison contract is violated.
  • 7. Re: java.lang.IllegalArgumentException: Comparison method violates general.....
    sabre150 Expert
    Currently Being Moderated
    1001805 wrote:
    Yes, very true. What pattern of data (equal elements, ascending, descending etc) can cause this comparator throw the exception java.lang.IllegalArgumentException while passing it as a parameter to Collections.sort?.
    The comparator can't throw that exception! The comparator does not analyse itself.

    >
    I need this pattern of data or any sample data that fails this code. Any sample data with few elements that make the code fail will be of great help!!.
    I really don't understand what you are asking here.

    >
    Also, this exception can be thrown only if the size of the collection to be sorted is greater that 32 as per the JDK.
    Sorry but nothing in the Javadoc I have says anything about the magic number 32 and it surely is irrelevant since I can't see that Collections.sort() method analysing the comparator code (but see my later comment about compare(a,a) ).

    >
    JDK 1.7 uses binarysort to sort the elements if the collections size < 32 and does not throw the exception in this case.
    Surely irrelevant!

    >
    If the collection size is > 32 it uses Tim sort and also throws the exception if the comparison contract is violated.
    All I can imagine is that somewhere in the Collections.sort() method a comparator.compare(a,a) is done and it detects that zero is not returned.

    Whatever the source of the problem the solution is to fix the comparator so that it does not violate the contract!

    P.S. Should you not be working with templates.
  • 8. Re: java.lang.IllegalArgumentException: Comparison method violates general.....
    1004808 Newbie
    Currently Being Moderated
    To clarify further, let us consider the below example where al is an arraylist of Integer objects,

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

    What Integer objects should the arraylist contain so that the exception "java.lang.IllegalArgumentException: Comparison method violates general....." is thrown?.

    I can say that a random sample like Integer(1001), Integer(1000), Integer(1000), Integer(1004) does not throw the exception, even though it contains two equal integer objects.
  • 9. Re: java.lang.IllegalArgumentException: Comparison method violates general.....
    Kayaman Guru
    Currently Being Moderated
    1001805 wrote:
    What Integer objects should the arraylist contain so that the exception "java.lang.IllegalArgumentException: Comparison method violates general....." is thrown?.
    Why do you even care about that? You're breaking the contract and it's being noticed, which is somewhat exceptional since for example the equals() method won't tell you that if you implement it wrong.

    Why don't you write the compare method correctly?
  • 10. Re: java.lang.IllegalArgumentException: Comparison method violates general.....
    jtahlborn Expert
    Currently Being Moderated
    1001805 wrote:
    What Integer objects should the arraylist contain so that the exception "java.lang.IllegalArgumentException: Comparison method violates general....." is thrown?.
    easy enough, just figure out what collection violates line 746 here:

    http://www.docjar.com/html/api/java/util/TimSort.java.html
  • 11. Re: java.lang.IllegalArgumentException: Comparison method violates general.....
    1004808 Newbie
    Currently Being Moderated
    Thanks for the reply, had reached till this point in the timsort algorithm but couldn't figure out under what condition will any collection that is being sorted reach here.

    Had tried many combinations of data in arraylist but it never reached this point.

    Any idea on forming an arraylist with elements such that this condition gets executed will be of great help!!
  • 12. Re: java.lang.IllegalArgumentException: Comparison method violates general.....
    EJP Guru
    Currently Being Moderated
    This is all irrelevant. Your compare method needs to return zero if the objects are equal. That's all. Fixit.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points