Java 오류: 비교 방법이 일반 계약을 위반합니다.
저는 이에 대한 많은 질문을 보고 문제를 해결하려고 노력했지만, 1시간 동안 구글 검색과 많은 시행착오를 겪어도 여전히 수정이 되지 않습니다.여러분 중 몇몇은 그 문제를 알아채길 바랍니다.
내가 알 수 있는 건 이거야
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;
}
}
감 잡히는 게 없어요?
예외 메시지는 실제로 매우 알기 쉬운 메시지입니다.계약서에 기재되어 있는 것은 이행성입니다.A > B
★★★★★★★★★★★★★★★★★」B > C
후, 임의의 ★★★★★★★★★★에 대해서A
,B
★★★★★★★★★★★★★★★★★」C
A > C
종이와 연필로 확인해보니 당신의 코드에는 구멍이 거의 없는 것 같습니다.
if (card1.getRarity() < card2.getRarity()) {
return 1;
않다-1
card1.getRarity() > card2.getRarity()
.
if (card1.getId() == card2.getId()) {
//...
}
return -1;
-1
아이디 ' ' ' ' ' ' ' '''해야 .-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(); //watch out for overflow!
다음 클래스를 사용하여 Comparator의 이동성 오류를 식별할 수 있습니다.
/**
* @author Gili Tzabari
*/
public final class Comparators
{
/**
* Verify that a comparator is transitive.
*
* @param <T> the type being compared
* @param comparator the comparator to test
* @param elements the elements to test against
* @throws AssertionError if the comparator is not transitive
*/
public static <T> void verifyTransitivity(Comparator<T> comparator, Collection<T> elements)
{
for (T first: elements)
{
for (T second: elements)
{
int result1 = comparator.compare(first, second);
int result2 = comparator.compare(second, first);
if (result1 != -result2)
{
// Uncomment the following line to step through the failed case
//comparator.compare(first, second);
throw new AssertionError("compare(" + first + ", " + second + ") == " + result1 +
" but swapping the parameters returns " + result2);
}
}
}
for (T first: elements)
{
for (T second: elements)
{
int firstGreaterThanSecond = comparator.compare(first, second);
if (firstGreaterThanSecond <= 0)
continue;
for (T third: elements)
{
int secondGreaterThanThird = comparator.compare(second, third);
if (secondGreaterThanThird <= 0)
continue;
int firstGreaterThanThird = comparator.compare(first, third);
if (firstGreaterThanThird <= 0)
{
// Uncomment the following line to step through the failed case
//comparator.compare(first, third);
throw new AssertionError("compare(" + first + ", " + second + ") > 0, " +
"compare(" + second + ", " + third + ") > 0, but compare(" + first + ", " + third + ") == " +
firstGreaterThanThird);
}
}
}
}
}
/**
* Prevent construction.
*/
private Comparators()
{
}
}
'이렇게 하다'를 돼요.Comparators.verifyTransitivity(myComparator, myCollection)
을 사용하다
JDK 버전과도 관련이 있습니다.JDK6에서 정상적으로 동작할 경우 JDK7의 구현 방법이 변경되었기 때문에 JDK7에 문제가 있을 수 있습니다.
이것 좀 봐.
: 서서 by by by by by 가 사용하는 정렬 java.util.Arrays.sort
by ( 적적적적적적 )java.util.Collections.sort
아, 아, 아, 아, 아, 아, 아, 네.에서는, 「」를 하는 가 있습니다.IllegalArgumentException
「」가 했을 경우.Comparable
the the Comparable
에서는 이러한 했습니다.이전 구현은 이러한 상황을 묵살했다. 새 속성인 ""를 할 수 .java.util.Arrays.useLegacyMergeSort
마지소트
나는 정확한 이유를 모른다.그러나 정렬을 사용하기 전에 코드를 추가하는 경우.괜찮을 거예요.
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
다음 경우를 고려합니다.
ㅇㅇㅇㅇㅇ,o1.compareTo(o2)
출됩니니다다card1.getSet() == card2.getSet()
도 card1.getRarity() < card2.getRarity()
11을
ㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇ는,o2.compareTo(o1)
하다card1.getSet() == card2.getSet()
그럼 이쯤에서 .else
, , , 「 」card1.getId() == card2.getId()
cardType > item.getCardType()
을 다시 1번으로 하다
중에서 ★★★★★★★★★★★★★★★★★.o1 > o2
, , , , 입니다.o2 > o1
당신은 계약을 어겼습니다.
if (card1.getRarity() < card2.getRarity()) {
return 1;
「」의 경우는, 「」입니다.card2.getRarity()
card1.getRarity()
-1을 반환하지 않을 수 있습니다.
당신도 마찬가지로 다른 사건들을 놓치셨군요나는 이렇게 할 것이다. 너는 너의 의도에 따라 바꿀 수 있다.
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());
int comp=card1.getSet() - card2.getSet();
if (comp!=0){
return comp;
}
comp=card1.getRarity() - card2.getRarity();
if (comp!=0){
return comp;
}
comp=card1.getSet() - card2.getSet();
if (comp!=0){
return comp;
}
comp=card1.getId() - card2.getId();
if (comp!=0){
return comp;
}
comp=card1.getCardType() - card2.getCardType();
return comp;
}
}
것입니다.Comparator
실행.이 문서를 체크함으로써 다음 명령어를 구현해야 합니다.compare(o1, o2)
규칙을 준수하여 동등성 관계로서의 방법:
if
disc는 a.disc(b)입니다.true
then
compare는 「(a, b)」입니다.0
if
dev(0 a.dev(b)> 0then
은 b.syslog(a)< 0 btrue
if
b.timeout(0 a.timeout(b)> 0 † b.timeout(c)> 0then
disc > 은 a.disc(c) > 0 입니다.true
코드를 확인하여 고객의 구현이 하나 이상의 Comparator 계약 규칙을 위반하고 있는지 확인할 수 있습니다.정적 분석으로 찾기 어려운 경우 예외를 발생시킨 데이터를 사용하여 규칙을 확인할 수 있습니다.
, 요.n x 2 2D array
'''contests
2번으로 나누다의 경우 만, 의 입력에 가 발생했습니다 「 - 「 」 、 「 1 」 、 「 」
Arrays.sort(contests, (row1, row2) -> {
if (row1[0] < row2[0]) {
return 1;
} else return -1;
});
오류:-
Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.base/java.util.TimSort.mergeHi(TimSort.java:903)
at java.base/java.util.TimSort.mergeAt(TimSort.java:520)
at java.base/java.util.TimSort.mergeForceCollapse(TimSort.java:461)
at java.base/java.util.TimSort.sort(TimSort.java:254)
at java.base/java.util.Arrays.sort(Arrays.java:1441)
at com.hackerrank.Solution.luckBalance(Solution.java:15)
at com.hackerrank.Solution.main(Solution.java:49)
'어느 정도'라는 했어요.equals
되는 항목, 작음을 으로 지정해야 .모든 경우에 대해 반환되는 항목(보다 큼, 같음, 작음)을 명시적으로 지정해야 합니다.
Arrays.sort(contests, (row1, row2) -> {
if (row1[0] < row2[0]) {
return 1;
}
if(row1[0] == row2[0]) return 0;
return -1;
});
저도 같은 증상이 있었어요.스트림에서 정렬이 이루어지는 동안 다른 스레드가 비교 개체를 수정하고 있는 것으로 나타났습니다.이 문제를 해결하기 위해 객체를 불변의 임시 객체에 매핑하고 Stream을 임시 컬렉션으로 수집하여 정렬했습니다.
이 코드를 실행하려고 하면 다음과 같은 예외가 발생합니다.
public static void main(String[] args) {
Random random = new Random();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 50000; i++) {
list.add(random.nextInt());
}
list.sort((x, y) -> {
int c = random.nextInt(3);
if (c == 0) {
return 0;
}
if (c == 1) {
return 1;
}
return -1;
});
}
Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:777)
at java.util.TimSort.mergeAt(TimSort.java:514)
at java.util.TimSort.mergeCollapse(TimSort.java:441)
at java.util.TimSort.sort(TimSort.java:245)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1462)
at Test.main(Test.java:14)
그 이유는 Comparator를 실장할 때 A > B > B > C > C > A의 케이스에 적합할 수 있으며 정렬 방식이 실행되어 깨지기 때문입니다.Java는 이 경우를 throw 예외로 방지합니다.
class TimSort<T> {
.
.
.
else if (len1 == 0) {
throw new IllegalArgumentException(
"Comparison method violates its general contract!");
.
.
.
결론적으로, 이 문제에 대처하기 위해.비교기가 A > B 및 B > C 및 C > A의 대소문자를 충족하지 않는지 확인해야 합니다.
몇 가지 기준(날짜, 같은 날짜, 기타...)에 따라 정렬해야 했습니다.이전 버전의 Java를 탑재한 이클립스에서는 동작하던 것이 안드로이드에서는 동작하지 않게 되었습니다.비교 방법은 계약을 위반하고 있습니다.
StackOverflow에서 읽은 후 날짜가 같으면 compare()에서 호출한 함수를 따로 작성했습니다.이 함수는 기준에 따라 우선순위를 계산하고 -1, 0 또는 1을 반환하여 비교()합니다.이제 된 것 같아요.
는 다음과 .StockPickBean
. 하다
List<StockPickBean> beansListcatMap.getValue();
beansList.sort(StockPickBean.Comparators.VALUE);
public class StockPickBean implements Comparable<StockPickBean> {
private double value;
public double getValue() { return value; }
public void setValue(double value) { this.value = value; }
@Override
public int compareTo(StockPickBean view) {
return Comparators.VALUE.compare(this,view); //return
Comparators.SYMBOL.compare(this,view);
}
public static class Comparators {
public static Comparator<StockPickBean> VALUE = (val1, val2) ->
(int)
(val1.value - val2.value);
}
}
같은 에러가 발생했을 경우:
java.displaces를 클릭합니다.부정 인수예외:비교방법이 일반계약에 위배됩니다!
이 행을 변경했습니다.
public static Comparator<StockPickBean> VALUE = (val1, val2) -> (int)
(val1.value - val2.value);
대상:
public static Comparator<StockPickBean> VALUE = (StockPickBean spb1,
StockPickBean spb2) -> Double.compare(spb2.value,spb1.value);
이것으로 에러가 해결됩니다.
다음과 같이 간단한 작업을 수행하는 것은 어떨까요?
int result = card1.getSet().compareTo(card2.getSet())
if (result == 0) {
result = card1.getRarity().compareTo(card2.getRarity())
}
if (result == 0) {
result = card1.getId().compareTo(card2.getId())
}
if (result == 0) {
result = card1.getCardType().compareTo(card2.getCardType())
}
return result;
선호도 순으로 비교를 주문하면 됩니다.
언급URL : https://stackoverflow.com/questions/11441666/java-error-comparison-method-violates-its-general-contract
'source' 카테고리의 다른 글
Python의 MariaDB 커넥터를 원격 서버에 연결할 수 없습니다. (0) | 2022.12.04 |
---|---|
함수를 정의하기 위한 const의 적절한 사용 (0) | 2022.12.04 |
PHP에서는 오브젝트를 인스턴스화하고 같은 회선상에서 메서드를 호출할 수 있습니까? (0) | 2022.12.04 |
rewriteBatchedStatements=true를 사용하는 MySQL 및 JDBC (0) | 2022.12.04 |
Node.js에서 로컬 IP 주소를 가져옵니다. (0) | 2022.12.04 |