[英]Java Error: java.lang.IllegalArgumentException: Comparison method violates its general contract
I am working on a old application which was originally written in Java 6 and which was upgraded to Java 7 a couple of years ago.我正在开发一个旧应用程序,它最初是用 Java 6 编写的,几年前升级到 Java 7。
In this application i am using a Collection.Sort to sort a list with a custom compare
method by implementing Comparator
interface.在这个应用程序中,我使用 Collection.Sort 通过实现
Comparator
接口使用自定义compare
方法对列表进行排序。 Type of objects in the list are CompanySchedule
which have 3 properties companyName
, Schedule
and expirationdate
.列表中的对象类型是
CompanySchedule
,它具有 3 个属性companyName
、 Schedule
和expirationdate
。
List can contain multiple objects with same companyName
but with unique expiration date.列表可以包含多个具有相同
companyName
但具有唯一到期日期的对象。 Below compare function sorts the list in ascending order of companyName and with in the same companyName list descending order of expiration date.下面的比较函数按 companyName 的升序对列表进行排序,并在同一个 companyName 列表中按到期日期的降序排列。 Below is the method implementation.
下面是方法的实现。
public int compare(CompanySchedule c1, CompanySchedule c2) {
int returnVal = 0;
int value = c1.getCompany().getName().compareTo(c2.getCompany().getName());
if (value == 0){
if (c1.getUseExpirationDate() == null || c2.getUseExpirationDate() == null){
returnVal = -1;
}
else{
int chkdate = c1.getUseExpirationDate().compareTo(c2.getUseExpirationDate());
if (chkdate == 0){
returnVal = 0;
}
else if (chkdate > 0){
returnVal = -1;
}
else if (chkdate < 0){
returnVal = 1;
}
}
}
else if (value < 0){
returnVal = -1;
}
else if (value > 0){
returnVal = 1;
}
return returnVal;
}
I know that when the transitive property is not met in the compare method implementation above error java.lang.IllegalArgumentException: Comparison method violates its general contract
will be thrown.我知道当上面的compare方法实现中没有满足传递属性时,会抛出错误
java.lang.IllegalArgumentException: Comparison method violates its general contract
。
can some one help in identifying the where this method will violates the transitive property.有人可以帮助确定此方法将在哪里违反传递属性。 Thanks for the Help.
谢谢您的帮助。
I think that one problem is here:我认为一个问题就在这里:
if (c1.getUseExpirationDate() == null || c2.getUseExpirationDate() == null){
returnVal = -1;
}
If a.getUseExpirationDate() == null and also b.getUseExpirationDate() == null, you will get that a < b and b < a which means a < a.如果 a.getUseExpirationDate() == null 并且 b.getUseExpirationDate() == null,您将得到 a < b 和 b < a,这意味着 a < a。
This breaks consistency.这打破了一致性。 There might be more problems in this method but I have not checked it all.
这种方法可能有更多问题,但我还没有全部检查过。
Good luck.祝你好运。
EDIT编辑
How about this code?这段代码怎么样?
public int compare(CompanySchedule c1, CompanySchedule c2) {
int returnVal = 0;
int value = c1.getCompany().getName().compareTo(c2.getCompany().getName());
if (value == 0) {
if (c1.getUseExpirationDate() == null && c2.getUseExpirationDate() != null) {
returnVal = -1;
} else if (c1.getUseExpirationDate() != null && c2.getUseExpirationDate() == null) {
returnVal = 1;
} else if (c1.getUseExpirationDate() == null && c2.getUseExpirationDate() == null) {
returnVal = 0;
} else {
int chkdate = c1.getUseExpirationDate().compareTo(c2.getUseExpirationDate());
if (chkdate == 0) {
returnVal = 0;
} else if (chkdate > 0) {
returnVal = -1;
} else if (chkdate < 0) {
returnVal = 1;
}
}
} else if (value < 0) {
returnVal = -1;
} else if (value > 0) {
returnVal = 1;
}
return returnVal;
}
I have tried not to change it too much, for comparability, but it should be refactored.为了可比性,我尽量不对其进行太多更改,但应该对其进行重构。 Basically it determines that nulls are smaller than other values.
基本上它确定空值小于其他值。
I know I am late to this, once I found the solution I had basically forgotten I had asked this question.我知道我迟到了,一旦我找到了解决方案,我基本上忘记了我问过这个问题。 so as I mentioned the application was written in Java 6 and then was upgraded to Java 7, as per my understanding the internal implementation of Collections.
所以正如我所提到的,根据我对 Collections 内部实现的理解,该应用程序是用 Java 6 编写的,然后升级到 Java 7。 Sort method changes the algorithm used from Merge sort to Tim Sort, Merge Sort ignore the Transitivity property of the compare method implementation, however Tim sort required the the compare method implementation to be transitive else the above exception would be thrown, since we had an legacy app we did not want to change anything from the code so we used jvm argument java.util.Arrays.useLegacyMergeSort=true Merge Sort internally in the sort implementation
Sort 方法将使用的算法从 Merge sort 更改为 Tim Sort,Merge Sort 忽略了 compare 方法实现的 Transitivity 属性,但是 Tim sort 要求 compare 方法实现是可传递的,否则会抛出上述异常,因为我们有遗留应用程序我们不想更改代码中的任何内容,因此我们在排序实现中使用了 jvm 参数 java.util.Arrays.useLegacyMergeSort=true Merge Sort
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.