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.