我的一个应用程序曾经抛出一个IllegalArgumentException,指出比较方法违反了其一般合同。我找到了一些详细说明该问题的资源,例如 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6804124 和 http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#source,并希望在我的应用程序中解决此问题。
但我无法再现问题,因此无法知道我的修复是否正确。
在我努力重现的过程中,我试图尽可能地简化问题,并想出了一个看起来像这样的小类:
public class Sortee implements Comparable<Sortee>
{
/** a value to sort by */
public final int _x;
public Sortee(int x)
{
_x = x;
}
public int compareTo(Sortee o)
{
return 1;
}
}
我还创建了一个等效的比较器:
public class SorteeIncorrectComparator implements Comparator<Sortee>
{
public int compare(Sortee a, Sortee b)
{
return 1;
}
}
在另一个类中,我创建了一个Sortee对象列表,并调用Collections.sort()变量来引发IllegalStateException:
private static void sort()
{
List<Sortee> sortees = createSortees();
Collections.shuffle( sortees );
Collections.sort( sortees, new SorteeIncorrectComparator() );
Collections.shuffle( sortees );
Collections.sort( sortees );
}
但从未引发IllegalStateException。
我在Linux和Windows上尝试过,在Java1.7.0_21,23.21-b01的Windows上尝试过eclipse,并检查了属性java.util.Arrays.useLegacyMergeSort未设置。
我认为在compare方法中总是返回1会破坏契约,因为它既不可交换也不可传递。
为什么我永远不会得到非法状态异常?
我的实现实际上是可传递的。
我将比较方法更改为返回随机值,这会引发异常。
当比较器违反a=b和b=c时,我能够重现这一点
List<Integer> timSortTestList = new ArrayList<Integer>();
{
for(int i=0; i<100; ++i) {
timSortTestList.add(i);
timSortTestList.add(i);
timSortTestList.add(i);
}
Collections.shuffle(timSortTestList, new Random(42));
}
Comparator<Integer> broken = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
if (Math.abs(o1-o2) < 10) {
return Compare.EQUAL; // WRONG
}
return Ordering.natural().compare(o1, o2);
}
};
Collections.sort(timSortTestList, broken); // throws up
比较一下这个问题——也许发生这种情况时有一个一般规律。
public static void main(String[] args) {
Object[] array = new Object[37];
for (int i = 0; i < array.length; i++) {
array[i] = new Object();
}
Arrays.sort(array, new Comparator<Object>() {
private int result[] = {1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 0, -1, -1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
private int index;
@Override
public int compare(Object o1, Object o2) {
return result[index++];
}
});
}
作为实习的一部分,我被要求调查一个错误。一段代码正在抛出 Java . lang . illegalargumentexception:比较法违反了它的通用契约! 自定义通过查看自定义类的成员变量来比较两个自定义类: 此自定义类的 方法查看此自定义类的 成员变量。我们很难重现这种行为。我的下意识反应是将自定义中的 return 语句替换为 ,但我的团队怀疑这会解决问题。谁能提供任何见解?
我看到我的应用程序在一些中国 Android 手机上发生了很多崩溃,并出现错误:比较方法违反了其总合同! 我读过这与Collections.sort有关。 我不太确定的是,这是否是因为我的自定义比较器。 以下是错误发生的地方: 比较器是这样的: 所以我不太确定比较器是否搞砸了什么,或者我是否需要以不同的方式进行collections.sort调用 感谢任何帮助
这种异常的原因是什么: 我使用的比较器如下: 其中 parameter.getSomeValue: 在: 哪里: 我不能重现这个异常,但它有时会出现。此外,您能给出100%出现此问题的代码示例吗?
嗨,下面是我的比较器的比较方法。我不知道哪里出了问题。我查了关于堆栈溢出的其他类似标题的问题和答案,但不确定我的方法有什么问题,但我不断得到java.lang.IllegalArgument异常:比较方法违反了它的一般合同! 任何帮助将不胜感激 添加我得到的异常
问题内容: 您好,以下是我的比较器的比较方法。我不确定是什么问题。我在堆栈溢出时查找了其他类似标题的问题和答案,但不确定我的方法有什么问题,但我一直在获取java.lang.IllegalArgumentException:比较方法违反了它的一般约定! 任何帮助将不胜感激 添加我得到的异常 问题答案: 您的方法 不是可 传递的 。如果和,则必须等于。 现在考虑这种情况: 对于,和,假设方法返回以下
使用自定义比较器执行< code > Collection.sort using >时,我得到一个< code > Java . lang . illegalargumentexception:Comparison方法违反了它的一般约定 我理解这是一个问题,因为该方法是不可传递的。在我的比较器中,调用了多个方法,我确定了违反此规则的代码段。然而,我无法修复它,也看不到它的问题。