当前位置: 首页 > 知识库问答 >
问题:

如何重现一个“比较方法违反了它的一般合同”IllegalArgumentExc的

巫朝明
2023-03-14

我的一个应用程序曾经抛出一个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会破坏契约,因为它既不可交换也不可传递。

为什么我永远不会得到非法状态异常?

共有3个答案

徐安康
2023-03-14

我的实现实际上是可传递的。

我将比较方法更改为返回随机值,这会引发异常。

司寇旺
2023-03-14

当比较器违反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

比较一下这个问题——也许发生这种情况时有一个一般规律。

崔涵亮
2023-03-14
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方法违反了它的一般约定 我理解这是一个问题,因为该方法是不可传递的。在我的比较器中,调用了多个方法,我确定了违反此规则的代码段。然而,我无法修复它,也看不到它的问题。