У меня есть список массивов объектов, которые я хочу отсортировать в порядке убывания даты (сначала самое последнее). У класса Foo есть параметр String "createAt", который я использовал для определения переопределения сравнения с методом.
«createAt» может быть нулевым, пустым или недействительной датой.
@Override
public int compareTo(Foo foo) {
Date created = new Date(0);
Date otherCreated = new Date(0);
try {
created = Utils.getFormattedDate(createdAt);
} catch (Exception e) {
e.printStackTrace();
}
try {
otherCreated = Utils.getFormattedDate(foo.createdAt);
} catch (Exception e) {
e.printStackTrace();
}
return Long.compare(otherCreated.getTime(),created.getTime());
}
Для нулевых проверок я определил компаратор
public static final Comparator fooComparator = new Comparator<Foo>() {
@Override
public int compare(Foo o1, Foo o2) {
if (o1 ==null || o1.getCreatedAt() == null) {
return (o2 ==null || o2.getCreatedAt() == null) ? 0 : 1;
}
if (o2==null || o2.getCreatedAt() == null) {
return -1;
}
return o1.compareTo(o2);
}
};
Я пытаюсь использовать
ArrayList <Foo> fooList = ....
Collections.sort(fooList, fooComparator);
Но, запустив этот код в задании MapReduce на искре, я получаю "Метод сравнения нарушает его общий контракт"
Я пытался написать много переходных тестовых случаев, но они проходят. Чего мне не хватает?
Вот мой тест
@org.junit.Test
public void testCompare_Contract() {
Foo t2 = new Foo();
t2.setId(2L);
t2.setCreatedAt(formatter.format(new Date(2018, 10, 28, 0, 0, 0).getTime()));
t2.setText("Foo 2");
Foo t3 = new Foo();
t3.setId(3L);
t3.setCreatedAt(null);
t3.setText("Foo 3");
Foo t4 = new Foo();
t4.setId(4L);
t4.setCreatedAt(formatter.format(new Date(2018, 10, 30, 0, 0, 0).getTime()));
t4.setText("Foo 4");
assertEquals(1, t3.compareTo(t2));
assertEquals(-1, t2.compareTo(t3));
assertEquals(1, t3.compareTo(t4));
assertEquals(-1, t4.compareTo(t3));
assertEquals(1, t2.compareTo(t4));
assertEquals(-1, t4.compareTo(t2));
assertEquals(0, t2.compareTo(t2));
}