I have used list.sort()
to sort a list of objects with type Date
, and got java.lang.IllegalArgumentException: Comparison method violates its general contract! I feel quite confusing about this error.
The code as below shown
List<Date> list = new ArrayList<>(200);
Date now = new Date();
for (int i = 0; i < 200; ++i) {
int delta = ThreadLocalRandom.current().nextInt(2, 10);
list.add(DateUtils.addMinutes(now, delta));
}
list.sort((x, y) -> {
int cmp = x.before(y) ? -1 : 1;
return cmp;
});
I have searched on Google, and found many similar issues (Java error: Comparison method violates its general contract), which say that the comparator does not meet transitivity rule. However, it seems that Date.before
should follow transitivity rule.
And I know the comparator has an issue when comparing two same dates. For any two same date, say d1
, d2
, both cmp(d1, d2)
and cmp(d2, d1)
return 1.
However, if we replace the comparator, always return 1, no error throw out. How surprising!
list.sort((x, y) -> 1);
In the above example, I created lots duplicated date which used to reproduce the error. Even though I know how to solve the issue, I still want to know why using before()
would fail.
By the way, I tested it on JDK 8 and 11, both failed.