gpt4 book ai didi

java - 为什么此代码会抛出异常 - 比较方法违反了其一般契约

转载 作者:行者123 更新时间:2023-11-30 02:41:15 25 4
gpt4 key购买 nike

我使用以下抛出 IllegalArgumentException 的代码:

// Copyright (c) 2003-2014, Jodd Team (jodd.org). All Rights Reserved.

package jodd.util;

import java.util.Comparator;

/**
* Compares two strings in natural, alphabetical, way.
*/
public class NaturalOrderComparator<T> implements Comparator<T> {

protected final boolean ignoreCase;

public NaturalOrderComparator() {
ignoreCase = false;
}

public NaturalOrderComparator(boolean ignoreCase) {
this.ignoreCase = ignoreCase;
}

/**
* Compare digits at certain position in two strings.
* The longest run of digits wins. That aside, the greatest
* value wins.
*/
protected int compareDigits(String str1, int ndx1, String str2, int ndx2) {
int bias = 0;

while (true) {
char char1 = charAt(str1, ndx1);
char char2 = charAt(str2, ndx2);

boolean isDigitChar1 = CharUtil.isDigit(char1);
boolean isDigitChar2 = CharUtil.isDigit(char2);

if (!isDigitChar1 && !isDigitChar2) {
return bias;
}
if (!isDigitChar1) {
return -1;
}
if (!isDigitChar2) {
return 1;
}

if (char1 < char2) {
if (bias == 0) {
bias = -1;
}
} else if (char1 > char2) {
if (bias == 0) {
bias = 1;
}
} else if (char1 == 0 && char2 == 0) {
return bias;
}

ndx1++;
ndx2++;
}
}

public int compare(T o1, T o2) {
String str1 = o1.toString();
String str2 = o2.toString();

int ndx1 = 0, ndx2 = 0;
int zeroCount1, zeroCount2;
char char1, char2;

int result;

while (true) {
// only count the number of zeroes leading the last number compared
zeroCount1 = zeroCount2 = 0;

char1 = charAt(str1, ndx1);
char2 = charAt(str2, ndx2);

// skip over leading spaces or zeros in both strings

while (Character.isSpaceChar(char1) || char1 == '0') {
if (char1 == '0') {
zeroCount1++;
} else {
zeroCount1 = 0; // counts only last 0 prefixes, space char interrupts the array of 0s
}
ndx1++;
char1 = charAt(str1, ndx1);
}

while (Character.isSpaceChar(char2) || char2 == '0') {
if (char2 == '0') {
zeroCount2++;
} else {
zeroCount2 = 0;
}
ndx2++;
char2 = charAt(str2, ndx2);
}

// process digits

boolean isDigitChar1 = CharUtil.isDigit(char1);
boolean isDigitChar2 = CharUtil.isDigit(char2);

if (isDigitChar1 && isDigitChar2) {
result = compareDigits(str1, ndx1, str2, ndx2);
if (result != 0) {
// not equals, return
return result;
}
// equal numbers
if (zeroCount1 != zeroCount2) {
return zeroCount1 - zeroCount2;
}
}

if (char1 == 0 && char2 == 0) {
// the end; the strings are the same, maybe compare ascii?
return zeroCount1 - zeroCount2;
}

// check when one of the numbers is just zeros
if (isDigitChar1 || isDigitChar2) {
if (zeroCount1 != zeroCount2) {
return zeroCount2 - zeroCount1;
}
}

// checks when both numbers are zero
if (zeroCount1 != zeroCount2) {
return zeroCount1 - zeroCount2;
}

// compare chars
if (ignoreCase) {
char1 = Character.toLowerCase(char1);
char2 = Character.toLowerCase(char2);
}
if (char1 < char2) {
return -1;
}
if (char1 > char2) {
return 1;
}

ndx1++;
ndx2++;
}
}

/**
* Safe charAt.
*/
private static char charAt(String s, int i) {
if (i >= s.length()) {
return 0;
}
return s.charAt(i);
}
}

抛出异常:

java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:747)
at java.util.TimSort.mergeAt(TimSort.java:483)
at java.util.TimSort.mergeCollapse(TimSort.java:410)
at java.util.TimSort.sort(TimSort.java:214)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)

这由以下函数调用:

@Override
public int compare(final T o1, final T o2) {
int result;
final MyObject obj1 = (MyObject) o1;
final MyObject obj2 = (MyObject) o2;

return result = compareStringId(obj1.getStringId(),obj2.getStringId());

}

private int compareStringId(final String Id1, final String Id2) {
return super.compare((T) Id1, (T) Id2);
}

它在我们的本地计算机上运行良好,但在生产中失败,我们无法连接到该计算机来找出原因。您能帮忙吗

最佳答案

问题在于 Comparator 的实现不正确。根据 Java 文档,Comparator 必须同时具有自反性和传递性。在这种情况下,传递性得不到保证。之前的 Java 8 这不是一个大问题,即排序实现 (MergeSort) 不会抛出异常。 Java8 将默认排序实现更改为 TimSort,它对具有无效约定的比较器更加敏感,因此可能会引发异常。

但是,这对解决您的问题没有多大帮助。查看同类最新版本如何here 。它已升级为支持比较器合约,而且在某些边缘情况下效果更好,更不用说最初对重音的支持了。

关于java - 为什么此代码会抛出异常 - 比较方法违反了其一般契约,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41634643/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com