【问题标题】:Java: Sort method throwing error: Comparison method violates its general contractJava:排序方法抛出错误:比较方法违反其一般合同
【发布时间】:2021-12-26 16:41:02
【问题描述】:

嘿,我得到了这个小代码 sn-p,当我运行我的程序时它不起作用。我有一个包含对象的列表,并希望首先将它们按 2 种类型分开,然后按其名称的字母顺序对它们进行排序。但是当我运行程序时,总是会出现这个 java 错误,上面写着:比较方法违反了它的一般合同! 我真的希望有人可以帮助我。

List<RandomObject> list;
list.stream().sorted((o1, o2) -> {
    if(o1.getClass().equals(o2.getClass))
        return o1.getName().compareTo(o2.getName());
    if(o1.getClass == someClass1.class && o2.getClass() == someClass2.class)
        return -1;
    return 1;
    }) 

【问题讨论】:

  • list 包含哪些对象?除了someClass1someClass2 之外,它还有别的吗?
  • @Sweeper 是的,它不仅包含 2 种类型的对象,但其中只有 2 种对我来说很重要,其他的你可以说是“隐藏的”。
  • 什么是RandomObjectgetName() 方法在哪里定义? someClass1someClass2 变量是如何定义的?为什么你认为你的“隐藏”对象不会造成问题?

标签: java sorting comparator


【解决方案1】:

“总合同”是这样的:

a &lt; b 这里的意思是:a.compareTo(b) 返回一个负数)。

  • a.compareTo(a) 必须0
  • 如果a.compareTo(b)为0,b.compareTo(a)必须也是。1
  • 如果a &lt; b,则b &gt; a 是必需的
  • 如果a &lt; bb &lt; c,则a &lt; c 是必需的

这些规则看起来非常明显,但比你想象的要难。

您的代码在不知道时返回一个毯子1,这会轻易违反合同:这意味着如果您的代码不知道ab,那么a.compare(b)b.compareTo(a) 违反了合同(两者都返回1,这是不允许的)。

您显然也没有遵循 SO 说明:您编写了伪代码或以其他方式编辑了您的实际代码没有测试它,然后将其粘贴。我知道因为你的代码无法编译(在o2.getClass 之后缺少()。鉴于你不知道发生了什么(当你问这样的问题时),你不知道什么是重要的,什么不是,因此,问题也可能在于您在将实际代码转移到此问题时最终删除的内容。

[1] 任何给定的比较器/比较实现都可以将 2 个不相等的项目视为“处于同一级别”。这意味着什么取决于你将它传递给什么。例如,如果您认为“foo”和“bar”在比较方面是等效的("bar".compareTo("foo") 返回 0,反之亦然),则只能将一个放入 TreeSet,但您可以将两者放入list 然后list.sort() 它,这仅仅意味着它们将被任意排序。但是,您的比较操作仍然需要保持一致:"foo""bar" 不相等,但比较器可以将它们视为“等价”,但您必须然后使compare("foo", "bar")compare("bar", "foo") / "foo".compareTo("bar")"bar.compareTo("foo") 返回 0,否则你违反了合同。

【讨论】:

    猜你喜欢
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多