【问题标题】:Debug "Comparison method violates its general contract!"调试“比较方法违反了它的一般合同!”
【发布时间】:2013-08-21 18:20:10
【问题描述】:

我有一个自己的、相对复杂的字符串比较器和一个大的字符串列表(大约 100 个字符串,已经尝试减少但问题无法重现),在尝试使用 Java 7 进行排序时,对它们进行排序会产生上述错误。我猜,规则

if a < b and b < c then a < c

可能会被违反。找出违反合同的样品的最佳方法是什么?

【问题讨论】:

  • 你能发布你的实际代码吗?
  • 您的比较器有任何个单元测试吗?
  • 不减少列表;而是逐步减少 比较器,同时使用相同的输入集重现错误。然后发布仍然存在问题的 minimal 比较器。但是,到那时,您可能会很明显。
  • 发布比较器代码。这种类型的错误通常可以通过检查发现。
  • @RohitJain 示例代码见:stackoverflow.com/questions/18364904/…

标签: java sorting


【解决方案1】:

好的,我用蛮力的方式做到了:3 个嵌套循环来相互比较 3 个值并验证上述规则。现在找到了一个违反规则的样本。

【讨论】:

  • @Buffalo 它有点像这样: for (Node node1 : nodes1) for (Node node2 : nodes2) for (Node node3 : nodes3) if (node1.compareTo(node2) 0) alertVioaltionOfContract(node1,node2,node3);
【解决方案2】:

在您的 compare() 方法和 equals() / hashcode() 方法的开头添加调试消息(您正在覆盖它们吗?)

【讨论】:

  • 您投反对票的回复有什么问题?你会在一分钟内得到有问题的价值
  • 使用比较器时不应该使用equals和hashcode方法。
  • 你是对的,自定义比较器可能不需要它们。但是覆盖它们并没有什么坏处。
  • 覆盖它们对解决这个特定问题没有任何帮助。
  • 没错,那是无关紧要的想法。但调试消息可以。
【解决方案3】:

当遇到类似问题时,深入研究问题并找到违反一般契约的 A、b 和 c 集合的唯一方法是使用循环。

假设您有一个需要排序的list 和一个违反其合同的自定义comparator,您可以使用以下内容找到对象

for (int i = 0; i < list.size(); i ++) {
                for (int j = 0; j < list.size(); j ++) {
                    for (int k = 0; k < list.size(); k ++) {
                        Objects a = list.get(i);
                        Objects b = list.get(j);
                        Objects c = list.get(k);
                        if (comparator.compare(a, b) < 0
                                && comparator.compare(b, c) < 0
                                && comparator.compare(a, c) > 0) {
                            System.out.print(("Error...1");
                            System.out.print((a + ", " + i);
                            System.out.print((b + ", " + j);
                            System.out.print((c + ", " + k);
                        }
                        if (comparator.compare(a, b) > 0
                                && comparator.compare(b, c) > 0
                                && comparator.compare(a, c) < 0) {
                            System.out.print(("Error...2");
                            System.out.print((a + ", " + i);
                            System.out.print((b + ", " + j);
                            System.out.print((c + ", " + k);
                        }
                        if (comparator.compare(a, b) == 0
                                && comparator.compare(b, c) == 0
                                && comparator.compare(a, c) != 0) {
                            System.out.print(("Error...3");
                            System.out.print((a + ", " + i);
                            System.out.print((b + ", " + j);
                            System.out.print((c + ", " + k);

                        }
                            
                    }
                }
            }

这种方法我以前用过很多次,尤其是当你无法通过检查发现你的编码中的逻辑错误时。

我还在另一个帖子中找到了这个答案,该帖子有一个你可以使用的通用类

https://stackoverflow.com/a/35000727/4019094

【讨论】:

    猜你喜欢
    • 2015-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-15
    相关资源
    最近更新 更多