我看到了很多关于这个的问题,并试图解决这个问题,但经过一个小时的谷歌搜索和大量的尝试和错误,我仍然无法解决它。我希望你们中的一些人能理解这个问题。
这就是我得到的:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:835)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:453)
at java.util.ComparableTimSort.mergeForceCollapse(ComparableTimSort.java:392)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:191)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
at java.util.Arrays.sort(Arrays.java:472)
at java.util.Collections.sort(Collections.java:155)
...
这是我的比较仪:
@Override
public int compareTo(Object o) {
if(this == o){
return 0;
}
CollectionItem item = (CollectionItem) o;
Card card1 = CardCache.getInstance().getCard(cardId);
Card card2 = CardCache.getInstance().getCard(item.getCardId());
if (card1.getSet() < card2.getSet()) {
return -1;
} else {
if (card1.getSet() == card2.getSet()) {
if (card1.getRarity() < card2.getRarity()) {
return 1;
} else {
if (card1.getId() == card2.getId()) {
if (cardType > item.getCardType()) {
return 1;
} else {
if (cardType == item.getCardType()) {
return 0;
}
return -1;
}
}
return -1;
}
}
return 1;
}
}
你知道吗?
10条答案
按热度按时间vnjpjtjt1#
我在下面的一个类中遇到了同样的错误
StockPickBean
. 从以下代码调用:得到相同错误后:
illegalargumentexception:比较方法违反了它的一般约定!
我改了这句话:
收件人:
修复了错误。
9udxz4iz2#
但是,如果
card2.getRarity()
小于card1.getRarity()
你可能不会返回-1。你同样会错过其他的案子。我会这样做,你可以根据你的意图改变:
4ngedf3f3#
考虑以下情况:
第一,
o1.compareTo(o2)
被称为。card1.getSet() == card2.getSet()
碰巧是真的,事实也是如此card1.getRarity() < card2.getRarity()
,则返回1。那么,
o2.compareTo(o1)
被称为。再一次,card1.getSet() == card2.getSet()
这是真的。然后,跳到下面else
,那么card1.getId() == card2.getId()
碰巧是真的,事实也是如此cardType > item.getCardType()
. 再次返回1。从那以后,
o1 > o2
,和o2 > o1
. 你违反了合同。doinxwow4#
它还与jdk的版本有关。如果它在jdk6中做得很好,可能会出现您描述的JDK7中的问题,因为JDK7中的实现方法已经改变了。
看看这个:
description:使用的排序算法
java.util.Arrays.sort
以及(间接地)通过java.util.Collections.sort
已被替换。新的排序实现可能会引发IllegalArgumentException
如果它检测到Comparable
这违反了法律Comparable
合同。以前的实现默默地忽略了这种情况。如果需要以前的行为,可以使用新的系统属性,java.util.Arrays.useLegacyMergeSort
,以恢复以前的合并排序行为。我不知道确切的原因。但是,如果在使用sort之前添加代码。会没事的。
tf7tbtn25#
我遇到了一个类似的问题,当时我正试图解决一个问题
n x 2 2D array
命名contests
它是一个简单整数的二维数组。这在大多数情况下都有效,但有一次抛出了运行时错误input:-error:-
看了上面的答案,我试着添加一个条件
equals
我不知道为什么,但它起了作用。希望我们必须明确指定对于所有情况(大于、等于和小于)应该返回什么:a7qyws3x6#
我也有同样的症状。对我来说,当排序在流中进行时,另一个线程正在修改比较的对象。为了解决这个问题,我将对象Map到不可变的临时对象,将流收集到临时集合,并对其进行排序。
wixjitnu7#
我必须根据几个标准(日期,如果是同一个日期;其他事情。用旧版本的java在eclipse上工作的东西,在android上不再工作了:比较方法违反了契约。。。
在阅读了stackoverflow之后,我编写了一个单独的函数,如果日期相同,则从compare()调用该函数。此函数根据条件计算优先级,并返回-1、0或1进行比较()。它现在似乎起作用了。
liwlm1x98#
也可能是openjdk的错误(不是在这种情况下,但它是相同的错误)
如果像我这样的人偶然发现了这个关于
那么它也可能是java版本中的一个bug。我有一个比较器运行了几年,现在在一些应用程序。但它突然停止工作,在所有比较完成后抛出错误(我在返回“0”之前比较了6个属性)。
现在我刚刚发现了openjdk的错误报告:
jdk-8210311型
影响版本:8,11
修复版本:12
https://bugs.openjdk.java.net/browse/jdk-8210311
9nvpjoqh9#
异常消息实际上是非常描述性的。它提到的契约是可传递的:如果
A > B
以及B > C
那么对于任何A
,B
以及C
:A > C
. 我用纸和铅笔检查了一下,你的代码似乎有几个洞:你不回来了
-1
如果card1.getRarity() > card2.getRarity()
.你回来了
-1
如果ID不相等。你应该回来-1
或者1
取决于哪个id更大。看看这个。除了更具可读性之外,我认为它实际上应该起作用:
js81xvg610#
您可以使用以下类来确定比较器中的传递性错误:
简单地调用
Comparators.verifyTransitivity(myComparator, myCollection)
在失败的代码前面。