Java错误:比较方法违反其一般合同 [英] Java error: Comparison method violates its general contract
问题描述
我看到很多问题,并试图解决这个问题,但经过一小时的谷歌搜索和大量的试验,错误,我仍然无法解决它。
prettyprint-override> java.lang.IllegalArgumentException:比较方法违反了它的一般合同!
at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:835)
在java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:453)
在java.util.ComparableTimSort.mergeForceCollapse (ComparableTimSort.java:392)
在java.util.ComparableTimSort.sort(ComparableTimSort.java:191)
在java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
at java.util.Arrays.sort(Arrays.java:472)
在java.util.Collections.sort(Collections.java:155)
在magiccollector.gui.Main $ 1.actionPerformed(Main.java :85)
at org.pushingpixels.flamingo.api.common.AbstractCommandButton.fireActionPerformed(AbstractCommandButton.java:616)
at org.pushingpixels.flamingo.api.common.AbstractCommandButton $ ActionHandler.actionPerformed(AbstractCommandButton .java:568)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at org.pushingpixels.flamingo.api.common.model.ActionRepeatableButtonModel.setPressed(ActionRepeatableButtonModel.java:123 )
at org.pushingpixels.flamingo.internal.ui.common.BasicCommandButtonListener.mouseReleased(BasicCommandButtonListener.java:147)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
在java.awt.Component.processMouseEvent(Component.java:6504)
在javax.swing.JComponent.processMouseEvent(JComponent。 java:3321)
在java.awt.Component.processEvent(Component.java:6269)
在java.awt.Container.processEvent(Container.java:2229)
在java.awt .Component.dispatchEventImpl(Component.java:4860)
在java.awt.Container.dispatchEventImpl(Container.java:2287)
在java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
在java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
在java.awt.LightweightDispatcher.dispatchEvent( Container.java:4422)
在java.awt.Container.dispatchEventImpl(Container.java:2273)
在java.awt.Window.dispatchEventImpl(Window.java:2713)
在java .awt.Component.dispatchEvent(Component.java:4686)
在java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
在java.awt.EventQueue.access $ 000(EventQueue.java: 101)
at java.awt.EventQueue $ 3.run(EventQueue.java:666)
at java.awt.EventQueue $ 3.run(EventQueue.java:664)
at java.security .AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue $ 4.run(EventQueue.java:680)
at java.awt.EventQueue $ 4.run(EventQueue.java:678)
at java.security.AccessController.doPrivileged (Native Method)
at java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:76)
在java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
在java。 (EventDispatchThread.java:127)
在java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
在java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
在$ java.awt.EventDispatchThread.pumpEventsForHierarchy
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
在java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
在java.awt.EventDispatchThread.run (EventDispatchThread.java:90)
这是我的比较器:
@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;
}
}
有什么想法吗?
异常消息实际上是很描述性的。它提到的合同是
转移:if A> B
和 B> ,,和 C
: A> C
。我用纸和铅笔检查,你的代码似乎有几个洞: if(card1.getRarity()< card2 .getRarity()){
return 1;
您不会返回 -1
if card1.getRarity()> card2.getRarity()
。
if card1.getId()== card2.getId()){
// ...
}
return -1;
您返回 -1
t相等。您应该根据哪个ID较大,返回 -1
或 1
。
看看这个。除了更加可读,我认为它应该工作:
if(card1.getSet()> card2.getSet ()){
return 1;
}
if(card1.getSet()< card2.getSet()){
return -1;
};
if(card1.getRarity()< card2.getRarity()){
return 1;
}
if(card1.getRarity()> card2.getRarity()){
return -1;
}
if(card1.getId()> card2.getId()){
return 1;
}
if(card1.getId()< card2.getId()){
return -1;
}
return cardType - item.getCardType(); //注意溢出!
I saw many questions about this, and tried to solve the problem, but after one hour of googling and a lots of trial & error, I still can't fix it. I hope some of you catch the problem.
This is what I get:
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)
at magiccollector.gui.Main$1.actionPerformed(Main.java:85)
at org.pushingpixels.flamingo.api.common.AbstractCommandButton.fireActionPerformed(AbstractCommandButton.java:616)
at org.pushingpixels.flamingo.api.common.AbstractCommandButton$ActionHandler.actionPerformed(AbstractCommandButton.java:568)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at org.pushingpixels.flamingo.api.common.model.ActionRepeatableButtonModel.setPressed(ActionRepeatableButtonModel.java:123)
at org.pushingpixels.flamingo.internal.ui.common.BasicCommandButtonListener.mouseReleased(BasicCommandButtonListener.java:147)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
at java.awt.Component.processMouseEvent(Component.java:6504)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6269)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4860)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2713)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:680)
at java.awt.EventQueue$4.run(EventQueue.java:678)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
And this is my comparator:
@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;
}
}
Any idea?
解决方案 The exception message is actually pretty descriptive. The contract it mentions is transitivity: if A > B
and B > C
then for any A
, B
and C
: A > C
. I checked it with paper and pencil and your code seems to have few holes:
if (card1.getRarity() < card2.getRarity()) {
return 1;
you do not return -1
if card1.getRarity() > card2.getRarity()
.
if (card1.getId() == card2.getId()) {
//...
}
return -1;
You return -1
if ids aren't equal. You should return -1
or 1
depending on which id was bigger.
Take a look at this. Apart from being much more readable, I think it should actually work:
if (card1.getSet() > card2.getSet()) {
return 1;
}
if (card1.getSet() < card2.getSet()) {
return -1;
};
if (card1.getRarity() < card2.getRarity()) {
return 1;
}
if (card1.getRarity() > card2.getRarity()) {
return -1;
}
if (card1.getId() > card2.getId()) {
return 1;
}
if (card1.getId() < card2.getId()) {
return -1;
}
return cardType - item.getCardType(); //watch out for overflow!
这篇关于Java错误:比较方法违反其一般合同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!