条件空对象:比较方法违反了它的一般契约
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)
当一个或另一个未定义时,由您决定结果应该是什么。但无论您做什么,生成的代码都必须遵守合同。
场景
我得到了一个对象,它有一个 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)
当一个或另一个未定义时,由您决定结果应该是什么。但无论您做什么,生成的代码都必须遵守合同。