Я использовал list.sort()
, чтобы отсортировать список объектов с типом Date
, и получил java .lang.IllegalArgumentException: метод сравнения нарушает его общий контракт! Меня это довольно смущает ошибка.
Код, показанный ниже
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;
});
Я искал в Google и обнаружил много похожих проблем (Java ошибка: метод сравнения нарушает общий договор ), которые говорят о том, что компаратор не соответствует правилу транзитивности. Однако кажется, что Date.before
должно следовать правилу транзитивности.
И я знаю, что у компаратора есть проблема при сравнении двух одинаковых дат. Для любых двух одинаковых дат, скажем, d1
, d2
, оба cmp(d1, d2)
и cmp(d2, d1)
возвращают 1.
Однако, если мы заменяем компаратор, всегда возвращаем 1, ошибка не выводится. Как удивительно!
list.sort((x, y) -> 1);
В приведенном выше примере я создал дублированную дату лотов, которая использовалась для воспроизведения ошибки. Несмотря на то, что я знаю, как решить эту проблему, я все же хочу знать, почему использование before()
даст сбой.
Между прочим, я тестировал его на JDK 8 и 11, оба отказались.