比较方法违反了它的一般契约——如何避免
Comparison method violates its general contract - how to avoid it
我知道这个问题可能有一些非常好的解释,但我仍然无法将其应用到我的代码中。在我的案例中如何避免该错误?这是我的代码:
sampleList.sort((o1, o2) -> {
try {
if (o1.getDate() == null || o2.getDate() == null) return 0;
int i = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy").parse(o1.getDate()).compareTo(new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy").parse(o2.getDate()));
return i;
} catch (ParseException e) {
logger.error("Sorting failed", e);
}
return 0;
});
sampleList 是一个列表类型,包含字符串形式的日期。这是我得到的一个例外:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(Unknown Source)
at java.util.TimSort.mergeAt(Unknown Source)
at java.util.TimSort.mergeCollapse(Unknown Source)
at java.util.TimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at java.util.ArrayList.sort(Unknown Source)
at
如果您有解决问题的建议,请与我分享。谢谢。
compare(T o1, T o2)
的 javadoc 说:
the implementor must ensure that compare(x, y)==0
implies that sgn(compare(x, z))==sgn(compare(y, z))
for all z
.
您的实施未能满足合同的该部分。
如果您有 x = null, y = 1, z = 2
,您对 "null equals anything" 的实施意味着:
compare(x, y) == 0 // Precondition met
// 0
sgn(compare(x, z)) == sgn(compare(y, z)) // Contract violated!
// 0 -1
您的比较器无法正确处理空值和无法解析的日期。考虑以下情况:
假设您有两个非空日期 d1 和 d2 以及一个空日期 d3。
假设 d1 > d2.
你因此有
d1 > d2
d1 == d3
d2 == d3
因此,如果 d1 和 d2 都等于 d3,则它们也应该彼此相等,但它们不是。
首先将所有字符串转换为日期或 null。
然后使用将所有空值视为大于(或小于)所有非空值的比较器。 Comparator
具有将非空对象的比较器转换为处理空值的比较器的实用方法,方法是将它们全部放在最前面或最后。
我知道这个问题可能有一些非常好的解释,但我仍然无法将其应用到我的代码中。在我的案例中如何避免该错误?这是我的代码:
sampleList.sort((o1, o2) -> {
try {
if (o1.getDate() == null || o2.getDate() == null) return 0;
int i = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy").parse(o1.getDate()).compareTo(new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy").parse(o2.getDate()));
return i;
} catch (ParseException e) {
logger.error("Sorting failed", e);
}
return 0;
});
sampleList 是一个列表类型,包含字符串形式的日期。这是我得到的一个例外:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(Unknown Source)
at java.util.TimSort.mergeAt(Unknown Source)
at java.util.TimSort.mergeCollapse(Unknown Source)
at java.util.TimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at java.util.ArrayList.sort(Unknown Source)
at
如果您有解决问题的建议,请与我分享。谢谢。
compare(T o1, T o2)
的 javadoc 说:
the implementor must ensure that
compare(x, y)==0
implies thatsgn(compare(x, z))==sgn(compare(y, z))
for allz
.
您的实施未能满足合同的该部分。
如果您有 x = null, y = 1, z = 2
,您对 "null equals anything" 的实施意味着:
compare(x, y) == 0 // Precondition met
// 0
sgn(compare(x, z)) == sgn(compare(y, z)) // Contract violated!
// 0 -1
您的比较器无法正确处理空值和无法解析的日期。考虑以下情况:
假设您有两个非空日期 d1 和 d2 以及一个空日期 d3。 假设 d1 > d2.
你因此有
d1 > d2
d1 == d3
d2 == d3
因此,如果 d1 和 d2 都等于 d3,则它们也应该彼此相等,但它们不是。
首先将所有字符串转换为日期或 null。
然后使用将所有空值视为大于(或小于)所有非空值的比较器。 Comparator
具有将非空对象的比较器转换为处理空值的比较器的实用方法,方法是将它们全部放在最前面或最后。