比较对象的两个日期属性时出现异常 'Comparison Method Violates Its General Contract!'

Exception 'Comparison Method Violates Its General Contract!' when comparing two date properties of an object

首先,我已经看过很多关于这个异常的问题和答案,但大多数只是关于比较简单的整数或相同的属性。 我拥有的是一个有两个日期的对象,当一个日期为空时,我将使用另一个日期进行比较,例如 class:

public class MyClass {
  private LocalDate primaryDate;
  private LocalDate secondaryDate;
  private String Code;
}

比较方法为:

 private List<MyClass> sortByDates(final List<MyClass> listOfClass) {
    Comparator<MyClass> comparator = ((Comparator<MyClass>) (first, second) -> {
        if (first.getPrimaryDate() == null || second.getPrimaryDate() == null) {
            return first.getSecondaryDate().compareTo(second.getSecondaryDate());
        }
        return first.getPrimaryDate().compareTo(second.getPrimaryDate());
    }).reversed().thenComparing(MyClass::getCodeAsLong);

    return listOfClass.stream()
        .sorted(comparator)
        .collect(Collectors.toList());
}

Obs1:secondaryDate 永远不会为空,但我必须使用 primaryDate 作为第一个比较选项,并且 primaryDate 永远不会小于 secondaryDate
Obs2: Code 属性 保存为字符串但没有任何字母,所以可以转换为long

唯一的问题是您如何处理 primaryDate.
的 null 检查以下示例:

MyClass primaryDate secondaryDate
A null 1/1/2021
B 1/1/2023 1/1/2022
C 1/1/2024 1/1/2020

根据你的比较器,B > AA > C 这意味着 B > C
但是,当您将 B 与 C 进行比较时。B < C,这违反了“一般合同”。

一般来说,比较nullable字段时,我们可以利用nullsFirst or nullsLast:

Comparator<MyClass> comparator = Comparator.nullsFirst(Comparator
                                           .comparing(MyClass::getPrimaryDate))
                                           .thenComparing(MyClass::getSecondaryDate)
                                           .reversed()
                                           .thenComparing(MyClass::getCodeAsLong);