当前位置: 首页 > 知识库问答 >
问题:

Collections.sort()比较法违反其总合同

袁赞
2023-03-14

我试图使用比较器基于两个字符串的比较对数组列表进行排序,但我最终使用的比较方法违反了它的一般契约错误。如果字符串中出现空值比较,我该如何处理?

密码

Collections.sort(keyList, new DIMsComparator<DIM>(sortField));


public static class DIMsComparator<T> implements Comparator<T> {
    String sortField = "";

    public DIMsComparator(String sortField) {
        this.sortField = sortField;
    }

    public int compare(T obj1, T obj2) {
        if (!(obj1 instanceof DIM) || !(obj2 instanceof DIM))
            return obj1 instanceof DIM ? -1 : obj2 instanceof DIM ? 1 : 0;
        DIM dim1 = (DIM) obj1;
        DIM dim2 = (DIM) obj2;
        // Changes for Grouping enhancement starts
        /*
         * if(dim1.getGroupName() != "" || dim2.getGroupName() != "") return -1;
         */
        // Changes for Grouping enhancement ends
        if (dim1.isTextLine())
            return 1;
        if (dim2.isTextLine())
            return -1;
        String[] mySortFields = Util.split(this.sortField, ",");
        for (int i = 0; i < mySortFields.length; i++) {
            if (mySortFields[i].equals(""))
                break;
            int value = compare(dim1, dim2, mySortFields[i]);
            if (value == 0)
                continue;
            else
                return value;
        }

        return dim1.dimSeqNo > dim2.dimSeqNo ? 1 : dim1.dimSeqNo < dim2.dimSeqNo ? -1 : 0;
    }

错误

[err] java.lang.IllegalArgumentException: Comparison method violates its general contract!
[err]   at java.util.TimSort.mergeLo(TimSort.java:788)
[err]   at java.util.TimSort.mergeAt(TimSort.java:525)
[err]   at java.util.TimSort.mergeCollapse(TimSort.java:452)
[err]   at java.util.TimSort.sort(TimSort.java:256)
[err]   at java.util.Arrays.sort(Arrays.java:1856)
[err]   at java.util.ArrayList.sort(ArrayList.java:1471)
[err]   at java.util.Collections.sort(Collections.java:186)

共有2个答案

皇甫飞宇
2023-03-14

关于 [err] java.lang.IllegalArgumentException:比较方法违反了其总合同!

您的解决方案可能是不可传递的

如果 A == B 且 B == C,则 A 必须等于 C。

关于你的问题:

如果字符串中出现空比较,我该如何处理。

看看这个答案

if(str != null

你还应该看看这行 int value = compare(dim1, dim2, mySortFields[i]);我不确定它应该做什么。

希望这有帮助!

饶骁
2023-03-14

如 https://stackoverflow.com/a/11441813/4090157 中所述,异常消息意味着您的比较不遵循每个 compare(..) 方法的协定,即:

  1. 实现者必须确保所有xy compare(x,y)必须抛出异常,当且仅当 compare
  2. 实现者还必须确保关系是可传递的:<code>((compare(x,y)

代码中的一个错误是,如果第一个< code>dim是textline,则只考虑它:

if (dim1.isTextLine())
    return 1;
if (dim2.isTextLine())
    return -1;

因此,如果< code>dim1和< code>dim2都是文本行,则< code>compare(dim1,dim2)和< code>compare(dim2,dim1)都将返回< code>1,这违反了协定要求1。

而且比较(dim1, dim2, mysortFields[i])中也可能存在更多不一致,这是无法判断的,因为您没有为此函数添加源代码。

 类似资料:
  • 我已经在类上实现了Comaprable,它给了我比较方法违反了它的总合同!,由于有一些值返回为 null,代码如下 公共静态比较器名称比较器 = 新比较器() {

  • 我从上面得到了一个例外,我知道这里经常讨论SO。无论如何,其他人不会告诉我我的代码有什么问题。这些只是音乐专辑返回最后一首歌曲被添加到Android的MediaStore的时间,以毫秒为单位。这只在某些设备上发生! 代码:

  • 我有一个类 ,它看起来像这样: 接下来,我有<代码>列表 其中和是当前位置的纬度和经度。有时,代码会抛出异常 我知道,如果方法不满足传递条件,则会抛出此异常。我在这里找到了一些信息:比较方法违反了其总合同!我理解为什么在引用的问题中抛出异常,但我仍然不知道为什么在我的代码中抛出异常。 你能帮我一下吗?谢了。 更新 的列表用于的适配器。如果有新的GPS位置,则对中的数据进行排序。代码如下所示: 和方

  • 我收到以下错误:“比较方法违反了它的一般合同!”当使用下面的比较器时,我无法使用jUnit复制异常。我想知道是什么导致了这个问题,以及如何复制它。有其他人也有同样的问题,但不知道如何复制。 使用以下方法调用该代码: 感谢任何帮助。 额外信息:该错误似乎发生在Java utils中的TimSort类中,并来自一个名为mergeLo的方法。链接:http://grepcode.com/file/rep

  • 我目前正在Java中对集合进行排序。我收到了错误消息“比较方法违反了它的一般契约”。我也理解这个错误消息,但我(主要)使用Long类型的构建比较方法。所以我不知道,在这种情况下,排序方法仍然违反了契约。这是我的代码: 这里是错误:

  • 我有一个类字段,和。我需要使用对它们进行排序,但我得到了一个异常: java.lang.IllegalArgumentException:比较方法违反了它的一般约定! 我的< code>compareTo方法: 请帮我找出compareTo方法中的错误。谢了。