Метод сравнения нарушает его общий договор!Только Java 7 - PullRequest
34 голосов
/ 21 октября 2011

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

Объект 'crew' представляет членов экипажа с рангами и другимиПредметы.Сравнение должно быть сделано путем сравнения значения assign_rank, int, и, если это значение равно в обоих случаях, тогда логическое значение is_trainer должно иметь значение.

Этот метод прекрасно работал до тех пор, покакак он работал с Java <7. Но начиная с Java 7 я продолжаю получать это: </p>

java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeLo(ComparableTimSort.java:714)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:451)
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:376)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:182)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
at java.util.Arrays.sort(Arrays.java:472)
at java.util.Collections.sort(Collections.java:155)
at dormas_flightlog.Query.getCrew(Query.java:714)

Вот источник, где некоторые потенциально опасные части уже были закомментированы, но это все еще не делаетработа:

public class crew implements Serializable, Comparable<crew> {

private static final long serialVersionUID = 36L;
private int flightID = 0;
private int assigned_rank = 25;
private boolean is_trainer = false;
...


@Override
public int compareTo(crew him) {

    int myRank = this.getAssigned_rank();
    int hisRank = him.assigned_rank;

    if (this == him) {
        return 0;
    }
    if (myRank > hisRank) {
        return 1;
    }
    if (myRank < hisRank) {
        return -1;
    }
    if (myRank == hisRank) {
//            if (is_trainer && !o.is_trainer) {
//                i = 1;
//            }
//            if (!is_trainer && o.is_trainer) {
//                i = -1;
//            }
//            if (is_trainer && o.is_trainer) {
//                i = 0;
//            }
//            if (!is_trainer && !o.is_trainer) {
//                i = 0;
//            }
        return 0;
    }

    return 0;
}

@Override
public int hashCode() {
    int hash = 7;
    hash = 31 * hash + this.assigned_rank;
    hash = 31 * hash + (this.is_trainer ? 1 : 0);
    return hash;
}

@Override
public boolean equals(Object o) {

    if (this == o) {
        return true;
    }


    int myRank = this.getAssigned_rank();
    int hisRank = 0;

    if (o instanceof crew) {
        crew him = (crew) o;
        hisRank = him.assigned_rank;
    } else {
        return false;
    }

    if (myRank > hisRank) {
        return false;
    }
    if (myRank < hisRank) {
        return false;
    }
    if (myRank == hisRank) {
//            if (is_trainer && !o.is_trainer) {
//                i = 1;
//            }
//            if (!is_trainer && o.is_trainer) {
//                i = -1;
//            }
//            if (is_trainer && o.is_trainer) {
//                i = 0;
//            }
//            if (!is_trainer && !o.is_trainer) {
//                i = 0;
//            }
        return true;
    }

    return false;
}

}

Реализация equals () была просто попыткой решить эту проблему.Данное исключение приходит с или без равно ().Я не вижу, как метод compareTo нарушает его контракт.Любая помощь очень ценится .... однажды этот код должен работать с Java 7, и я не знаю, как ... Спасибо

Ответы [ 4 ]

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

см. Это:

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

Область: API: Сводка утилит: обновлено поведение сортировки для массивов и Коллекции могут выдавать исключение IllegalArgumentException

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

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

RFE: 6804124

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

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

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

4 голосов
/ 13 марта 2015

Я смог решить эту ошибку, потому что это была ошибка в jdk7.

здесь я нашел решение:

"Метод сравнения нарушает его общий контракт!" - TimSort и GridLayout

В основном мне просто нужно было добавить

JAVA_OPTS="$JAVA_OPTS -Djava.util.Arrays.useLegacyMergeSort=true"

моему jboss

0 голосов
/ 09 марта 2017

К сожалению, ни одно из решений не работает для Android. TimSort используется глубоко в Android ViewGroup, относящейся к addChildrenForAccessibility, который отображается в Java 7 и 8. Никакого пользовательского кода не участвует ни в каком сравнении.

Из других отчетов это связано с наличием RelativeLayout с перекрывающимися элементами, как это обычно делается. Например, TextView, который появляется над изображением, или два элемента в одном месте, где вы устанавливаете только один видимый за раз. https://code.google.com/p/android/issues/detail?id=55933

Я не нашел способа обойти ошибку. Вы не можете установить опцию -Djava в Android Studio или Eclipse (по крайней мере, я смог найти). Принудительное использование Java 1.6 должно работать, но не работает. Похоже, что новые планшеты и телефоны Amazon от Fire гораздо более чувствительны к этой ошибке, чем другие устройства.

Ходят слухи, что в Java 9 будет исправление, такое как опция времени выполнения, которая работает, но с ошибкой, которая существует уже много лет, я сомневаюсь, что она когда-нибудь будет исправлена, особенно с учетом вражды между Oracle и Google. Да, возможно, ошибка действительно глубоко в коде Android и должна быть там исправлена. Имея более миллиарда устройств, это нереальное решение для всех существующих устройств.

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