I was working on Comparable
interface and found that it is throwing IllegalArgumentException
when i put size=50
in the program below and is working fine when i put size =5
.
public class Test {
public static void main(String[] args) {
int size = 50;
Test compareTest = new Test();
compareTest.test(size);
}
public void test(int size) {
List<TestObject> requests = new ArrayList<TestObject>();
for (int index = 0; index < size; index++) {
TestObject request = new TestObject();
request.value = index;
requests.add(request);
}
Collections.sort(requests);
}
}
class TestObject implements Comparable<TestObject> {
public int value;
public int compareTo(TestObject req) {
if (value % 3 == 0) {
return -1;
} else if (value % 3 == 1) {
return 0;
}
return 1;
}
}
I am not sure about the root cause of this problem, can some one help me on this.
Exception stack trace is given below.
Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeLo(ComparableTimSort.java:744)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:481)
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:406)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:213)
You violate the Comparable contract.
Actually you don't compare two objects between them but you compare only the value
field of the current TestObject
object according to the result of modulo of 3. You don't use the TestObject
object passed as parameter in the compareTo()
method.
Suppose you have a List
of two TestObject
objects with 3
as value
field
The two objects will return -1
:
if (value % 3 == 0) {
return -1;
}
But according to the rule :
The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an exception.)
Assuming the first object is x
and the second object is y
.
If y.compareTo(x)
returns a negative number (such as -1), so x.compareTo(y)
should return a positive number (such as 1).
I was working on Comparable interface and found that it is throwing IllegalArgumentException when i put size=50 in the program below and is working fine when i put size =5
In fact when you violate the Comparable
contract, the results are not predictable. It may work with some specific values, don't work with other specific values.
It may work in a specific JVM version and don't work in another one.
Trying to understand why it fails or it successes for a specific value may be interesting but it is really not helpful.
Trying to understand the contract in order to respect it is much better.
Because today it works is in way but tomorrow in a future implementation, it could change. Only the API is a guarantee.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With