调试"比较方法违反其通用契约!"

3

我有一个相对高级的字符串比较器和一个包含大量字符串(大约100个字符串,已经尝试过缩减但问题无法重现)的列表。当我尝试使用Java 7进行排序时,会产生上述错误。我猜测规则

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

可能会违反合同。如何找到一个违反合同的样本?


2
你能贴出你的实际代码吗? - Rohit Jain
你有为你的比较器编写任何单元测试吗? - Raedwald
2
不要缩小列表;而是逐步减小“比较器”,同时使用相同的输入集合重现错误。然后发布仍然存在问题的“最小”比较器。然而,在这一点上,可能会对你变得明显。 - Marko Topolnik
3
请发布比较器代码。这种类型的错误通常可以通过检查找到。 - Jim Garrison
@RohitJain 请查看以下示例代码:https://dev59.com/0XXZa4cB1Zd3GeqPAPOp#96ygEYcBWogLw_1bmPpw - Torsten
3个回答

6

好的,我用蛮力解决了它: 3个嵌套循环来比较3个值并验证上述规则。现在找到了一个违反该规则的示例。


4
@水牛,代码大致如下: for (Node node1 : nodes1) for (Node node2 : nodes2) for (Node node3 : nodes3) if (node1.compareTo(node2) < 0 && node2.compareTo(node3) < 0 && node1.compareTo(node3) > 0) alertVioaltionOfContract(node1,node2,node3); - Torsten

1
在您的compare()方法开始处添加调试信息,并对equals() / hashcode()方法进行修改(您正在覆盖它们吗?)

你为什么要给这个回复点踩?你的值可能会在一分钟内出现问题。 - Leos Literak
当使用比较器时,不应使用equals和hashcode方法。 - Thomas S.
你是对的,自定义比较器可能不需要它们。但重写它们也没有坏处。 - Leos Literak
1
覆盖它们对解决这个特定问题没有任何帮助。 - Thomas S.
没错,那个想法不相关。但调试信息是必需的。 - Leos Literak

0
当面临类似问题时,深入挖掘问题并找到违反一般合同的 A、b 和 c 的集合的唯一方法是使用循环。 假设您有一个需要排序的列表和一个违反其契约的自定义比较器,您可以使用类似下面的代码来查找对象。
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://dev59.com/fGgu5IYBdhLWcg3wRlL0#35000727


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接