条件空对象:比较方法违反了它的一般契约

Conditional Null Object: Comparison method violates its general contract

场景

我得到了一个对象,它有一个 startDate 和一个 endDate。如果两者都是 not null 将设置timeDiff,计算Long中这两个日期之间的时差。

用例

所有带有 timeDiff 的对象应该在最前面,其余的在最后。

比较器

HFehlerProtPairComparator

if (sortFieldName.equals(HFehlerProtPairFields.EREIGNISDATUM_DIFFERENZ.getName())) {
            if (null != firstO.getStartDate() && null != firstO.getEndDate()
                    && null != secondO.getStartDate() && null != secondO.getEndDate()) {
                compare = firstO.getTimeDiff().compareTo(secondO.getTimeDiff());
            } else {
                compare = -1;
            }

        }

我不知道我错过了什么,调试对我没有帮助。我尝试在纸上验证它,但我也没有看到我的错误。

调用层级

comp = new HFehlerProtPairComparator(field.getName(), SortType.ASC.name());
Error ==> Collections.sort(unsortedHFehlerProtPairList, comp);

堆栈

at java.util.TimSort.mergeHi(TimSort.java:899)
at java.util.TimSort.mergeAt(TimSort.java:516)
at java.util.TimSort.mergeForceCollapse(TimSort.java:457)
at java.util.TimSort.sort(TimSort.java:254)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1454)
at java.util.Collections.sort(Collections.java:175)
at uebergreifendeereignis.UeHFehlerProtPairListController.sortBySortMap(UeHFehlerProtPairListController.java:360)

如果您有一个既没有设置 startDate 也没有设置 endDate 的对象,并且您将它与自身进行比较,则您的比较器会给出 -1 作为结果。结果应该是 0,因为一个对象不应该小于它自己..

问题是在某些情况下,您的代码 returns -1 在比较 A 和 B 以及比较 B 和 A 时。例如,假设您有对象 A,它没有开始日期和没有结束日期的对象 B。现在,当使用参数列表 (A, B) 调用比较器时,它 returns -1,表示 A 小于 B.

但稍后,可能会使用参数列表调用比较器(B, A)。它也是returns -1,意思是B < A.

这违反了比较器的合同。规则说如果比较器 returns -1 对于 (A, B),那么它必须 return 1 对于 (B, A)。也就是说,如果 A < B,则 B > A。您的代码不符合该约定。

为了使您的代码正常工作,您必须确定在未定义开始或结束时间时比较时差的含义。如果 A.startDate 为空,则 timeDiff 未定义。如果 B 有一个有效的时间差异,B 应该被认为大于、等于还是小于 A?

与我之前的回答一样,您需要考虑几个条件。

A.timeDiff  B.timeDiff    result
 undefined   undefined    equal
 undefined   valid        ??
 valid       undefined    ??
 valid       valid        A.timeDiff.compareTo(B.timeDiff)

当一个或另一个未定义时,由您决定结果应该是什么。但无论您做什么,生成的代码都必须遵守合同。