java – “比较方法违反其一般合同”仅在某些情况下被抛出
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java – “比较方法违反其一般合同”仅在某些情况下被抛出,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3461字,纯文字阅读大概需要5分钟。
内容图文
![java – “比较方法违反其一般合同”仅在某些情况下被抛出](/upload/InfoBanner/zyjiaocheng/754/5e687ad1ead8457e950c61c353a74e0a.jpg)
首先,我知道许多其他线程都描述了这个问题.但是我无法找到并回答这个问题,为什么不总是抛出这个错误?
让我来描述一下我的意思.我写了一些示例代码来说明这一点:
public class Mushroom {
public int size;
public Mushroom(int size) {
this.size = size;
}
@Override
public boolean equals(Object obj) {
//this is intentionally false - read in description
return false;
}
}
DSA
public class MushroomComparator implements Comparator<Mushroom> {
@Override
public int compare(Mushroom o1, Mushroom o2) {
// here is the code which breaks the contract
if (o1.size < o2.size){
return 1;
}else if(o1.size >o2.size){
return -1;
}
return 1;
}
}
最后测试比较:
public class ComparisonTest {
public static void main(String[] args) {
// System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
List<Mushroom> forest = new ArrayList<>();
for(int i =0; i<18; i++){
Mushroom mushroom1 = new Mushroom(1);
Mushroom mushroom2 = new Mushroom(3);
Mushroom mushroom3 = new Mushroom(2);
forest.add(mushroom1);
forest.add(mushroom2);
forest.add(mushroom3);
}
Collections.sort(forest, new MushroomComparator());
}
}
在运行时,我们将收到此描述的问题
java.lang.IllegalArgumentException: Comparison method violates its
general contract!
根据Collections.sort方法的文档:
(optional) if the implementation detects that the natural ordering of the list elements is found to violate the Comparable contract
那么让我们回答一下这个问题在Comparable的文档中这个合同是什么(在我的例子中我使用Comparator,但是从文档中它应该满足相同的要求)
The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y
这个规则我故意打破以获得我正在写的错误.这是compareTo方法的实现应该遵循的规则之一.其余的都在文档中描述,但一般来说,据我所知,文档的等价关系应该得到满足
It follows immediately from the contract for compareTo that the quotient is an equivalence relation on C, and that the natural ordering is a total order on C
现在真正困扰我的是我的测试方法中迭代次数变化的结果.如果您将数字从18更改为22,那么将不会抛出异常.此异常被描述为Optional,因此它确实意味着有时会抛出此异常,有时则不会.我没有深入研究排序算法的新实现(TimSort)(change of sort agorithm since Java 7).我明白,为了打破比较器合同,检查每组数据可能会耗费一些CPU消耗,但是有时候会有什么意图表明,有时甚至没有.这可能真的很有误导性.
Morover我可以将比较方法的实现更改为简单..返回1.根据文档,它应该违反合同.但事实并非如此.
在文档中也保留了与equals方法的合同,但实际上并不需要
It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y))
并且在我的示例中检查它我已经实现了equals方法以返回始终为false.有了这个,我确信equals方法不会强制破坏比较器合同.
现在我的问题是:比较器的真正合同是什么(在破坏它的背景下)?为什么对于某些数据集会引发此异常,而对于其他数据则不会?也许我错过了什么?最后但并非最不重要的是 – 需要打破哪些规则才能抛出此异常?
需要注意的是,对此的解决方案可能会关闭排序算法的新实现,如here所述,并在我的示例代码中进行了评论.
解决方法:
why this error is not always thrown
因为Collections.sort的工作不是验证你的比较方法.它的工作只是实现排序.但这样做的逻辑可以揭示无效的比较方法作为其在某些条件分支中的逻辑的副产品.在这种情况下,抛出而不是尝试继续使用无效的比较方法进行排序是有意义的.
What is really contract of comparator (in context of breaking it) ?
如果你违反合同,排序可能无法正常运行,或者根本没有. (并不是说它会验证你的比较方法.)
Why for some set of data this exception is thrown and for other not ?
如果排序没有遵循导致排序代码可以检测到的逻辑缺陷的路径,则它将不知道要抛出.但是正在使用的TimSort确实发生了一个逻辑分支,它揭示了无效的比较方法,所以它确实抛出了.
内容总结
以上是互联网集市为您收集整理的java – “比较方法违反其一般合同”仅在某些情况下被抛出全部内容,希望文章能够帮你解决java – “比较方法违反其一般合同”仅在某些情况下被抛出所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。