Search code examples
javacomparatorcomparableillegalstateexception

How to reproduce a "Comparison method violates its general contract" IllegalArgumentException


One of my applications once threw an IllegalArgumentException stating that the Comparison method violates its general contract. I've found some sources detailing the problem like https://bugs.java.com/bugdatabase/view_bug?bug_id=6804124 and http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#source and wanted to fix this in my application.

But I can not reproduce the problem hence can not know if my fix is correct.

In my efforts to reproduce, I tried to simplify the problem as much as possible and came up with a little class that looks like this:

public class Sortee implements Comparable<Sortee>
{
  /** a value to sort by */
  public final int _x;

  public Sortee(int x)
  {
    _x = x;
  }

  public int compareTo(Sortee o)
  {
    return 1;
  }
}

I've also created an equivalent as Comparator:

public class SorteeIncorrectComparator implements Comparator<Sortee>
{
  public int compare(Sortee a, Sortee b)
  {
    return 1;
  }
}

In another class I created a List of Sortee objects and called the Collections.sort() variants to provoke the IllegalStateException:

private static void sort()
{
   List<Sortee> sortees = createSortees();

   Collections.shuffle( sortees );
   Collections.sort( sortees, new SorteeIncorrectComparator() );

   Collections.shuffle( sortees );
   Collections.sort( sortees );
}

But the IllegalStateException is never raised.

I've tried it on Linux and Windows and in eclipse on Windows with Java 1.7.0_21, 23.21-b01 and checked that property java.util.Arrays.useLegacyMergeSort is not set.

I thought that always returning 1 in the compare method should break the contract, as it is neither commutative nor transitive.

Why do I never get an IllegalStateException?


Solution

  • My implementation actually was transitive.

    I've changed the compare method to return random values and that raises the Exception.