почему мой метод сравнения выдает исключение - метод сравнения нарушает свой общий контракт! - PullRequest
14 голосов
/ 08 июля 2011

Почему этот код

public class SponsoredComparator implements Comparator<SRE> {

    public boolean equals(SRE arg0, SRE arg1){
        return arg0.getSponsored()==arg1.getSponsored();
    }

    public int compare(SRE object1, SRE object2) {
        Log.d("SponsoredComparator","object1.getName() == "+ object1.getName());
        Log.d("SponsoredComparator","object1.getSponsored() == "+ object1.getSponsored());
        Log.d("SponsoredComparator","object2.getName() == "+ object2.getName());
        Log.d("SponsoredComparator","object2.getSponsored() == "+ object2.getSponsored());
        Log.d("SponsoredComparator","compare return == "+ (object1.getSponsored() && object2.getSponsored() ? 0 : object1.getSponsored() ? -1 : 1));
        return object1.getSponsored() && object2.getSponsored() ? 0 : object1.getSponsored() ? -1 : 1;
    }
}

выбросить это исключение: ERROR/AndroidRuntime(244): java.lang.IllegalArgumentException: Comparison method violates its general contract!<br> ERROR/AndroidRuntime(4446): at java.util.TimSort.mergeLo(TimSort.java:743)

Метод sre.getSponsored () возвращает логическое значение.

Спасибо.

Ответы [ 7 ]

27 голосов
/ 08 июля 2011

Я подозреваю, что проблема возникает, когда не поддерживается ни значение . Это вернет 1, как вы это называете, то есть

x1.compare(x2) == 1

x2.compare(x1) == 1

Это неверно.

Я предлагаю вам изменить это:

object1.getSponsored() && object2.getSponsored()

до

object1.getSponsored() == object2.getSponsored()

в обоих местах. Я, вероятно, на самом деле извлекаю метод где-то с такой сигнатурой:

public static int compare(boolean x, boolean y)

и затем назовите это так:

public int compare(SRE object1, SRE object2) {
    return BooleanHelper.compare(object1.getSponsored(), object2.getSponsored());
}

Это сделает код более понятным, ИМО.

19 голосов
/ 07 декабря 2011

Я предполагаю, что вы используете JDK 7. Проверьте следующий URL:

Из http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#source

Область: API: Утилиты

Сводка: ОбновленоПоведение сортировки для Arrays и Collections может вызвать IllegalArgumentException

Описание: Алгоритм сортировки, используемый java.util.Arrays.sort и (косвенно) java.util.Collections.sort, был заменен.Новая реализация сортировки может выдать IllegalArgumentException, если обнаружит Comparable, который нарушает контракт Comparable.Предыдущая реализация молча игнорировала такую ​​ситуацию.Если требуется предыдущее поведение, вы можете использовать новое системное свойство java.util.Arrays.useLegacyMergeSort для восстановления предыдущего поведения сортировки слиянием.

Природа несовместимости: поведенческая

RFE: 6804124

Более подробную информацию см. В базе данных ошибок , ссылка здесь .

8 голосов
/ 08 июля 2011

Контракт между equals () и compareTo () заключается в том, что когда equals () возвращает true, compareTo () возвращает 0, а equals () - false, CompareTo возвращает -1 или + 1.

Кстати: я предполагаю, что ваш метод compare () вызывается не очень часто, поскольку сообщения отладки будут занимать значительное количество ресурсов процессора и памяти.

1 голос
/ 24 июля 2014

Я согласился со всеми ответами, в частности, с Джоном, но я хочу сказать, что я должен сказать, что мы всегда должны проверять нулевую безопасность в методе сравнения, чтобы наш метод никогда не ломался, и это хорошая привычка в программировании - всегда проверять ноль.Для получения дополнительной информации смотрите здесь

0 голосов
/ 16 сентября 2018

Мое решение: когда я хочу отсортировать числа и элемент массива равен нулю, я ставлю 0, тогда ошибка исчезает.Необходимо позаботиться о том, чтобы размеры каждого ряда в двумерных массивах были одинаковыми.

0 голосов
/ 21 октября 2016

У меня сегодня та же проблема в веб-приложении.Четыре вызова, работающие с одним и тем же массивом, пытались отсортировать его одновременно, фактически перепутывая друг друга.

0 голосов
/ 29 марта 2013

возможно, у вас просто есть значения NaN, которые вы сравниваете через Collections.sort ... для меня это было проблемой, и я получил это исключение, даже имея правильную реализацию метода сравнения (obj1, obj2)!Проверьте это!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...