0

我知道这个问题可能有一些非常好的解释,但我仍然无法将它应用到我的代码中。在我的情况下如何避免该错误?这是我的代码:

        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 

如果您对如何解决它有任何建议,请与我分享。谢谢你。

4

2 回答 2

1

的 javadoccompare(T o1, T o2)说:

实施者必须确保这compare(x, y)==0意味着sgn(compare(x, z))==sgn(compare(y, z))所有z.

您的实施未能满足合同的该部分。

如果你有x = null, y = 1, z = 2,你的“null 等于任何东西”的实现,意味着:

compare(x, y) == 0   // Precondition met
//    0

sgn(compare(x, z)) == sgn(compare(y, z))   // Contract violated!
//      0                   -1
于 2019-12-12T22:33:14.663 回答
1

您的比较器没有正确处理空值和不可解析的日期。考虑以下情况:

假设您有两个非空日期 d1 和 d2 以及一个空日期 d3。假设 d1 > d2。

你因此有

d1 > d2
d1 == d3
d2 == d3

因此,如果 d1 和 d2 都等于 d3,那么它们也应该彼此相等,但事实并非如此。

首先将所有字符串转换为日期或 null。

然后使用一个比较器,它认为所有空值都大于(或低于)所有非空值。Comparator具有将非空对象的比较器转换为比较器的实用方法,该比较器通过将它们全部放在首位或最后来处理空值。

于 2019-12-12T22:33:23.153 回答