Метод сравнения нарушает его общий контракт! Только Java 7
Я знаю, что это было проблемой какое-то время, и проверил все предыдущие ответы, которые я мог получить, но все же этот не работает.
Объект "экипаж" представляет членов экипажа со званиями и другими предметами. Сравнение должно проводиться путем сравнения "assign_rank", значения int, и если это значение равно в обоих случаях, тогда "is_trainer", логическое значение, должно иметь значение.
Этот метод работал отлично, пока он работал с java < 7. Но с Java 7 я продолжаю получать следующее:
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, и я не знаю, как...
Благодаря
Ответы
Ответ 1
см. это:
Из http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#source
Область: API: Утилиты Синопсис: Обновлен порядок сортировки для массивов и Коллекции могут вызывать исключение IllegalArgumentException
Описание: алгоритм сортировки, используемый java.util.Arrays.sort и (косвенно) с помощью java.util.Collections.sort был заменен. Новый сортировка может вызвать исключение IllegalArgumentException, если оно обнаруживает Сопоставимый, который нарушает договор Сопоставимости. Предыдущий реализация молча игнорировала такую ситуацию. Если предыдущий поведение желательно, вы можете использовать новую систему свойство java.util.Arrays.useLegacyMergeSort, чтобы восстановить предыдущий mergesort.
Характер несовместимости: поведенческий
RFE: 6804124
Для получения более подробной информации см. базу данных ошибок здесь.
Ответ 2
возможно, у вас есть только значения NaN
, которые вы сравниваете с помощью Collections.sort(...)
, это было проблемой для меня, и я получил это исключение, даже имея правильную реализацию метода compare(obj1, obj2)
! Проверьте это!
Ответ 3
Я смог решить эту ошибку, потому что это была ошибка в jdk7.
здесь я нашел решение:
"Метод сравнения нарушает его общий контракт!" - TimSort и GridLayout
В основном мне просто нужно было добавить
JAVA_OPTS="$JAVA_OPTS -Djava.util.Arrays.useLegacyMergeSort=true"
к моему jboss
Ответ 4
К сожалению, ни одно из решений не работает для 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 newer Fire и телефоны гораздо более чувствительны к этой ошибке, чем другие устройства.
Есть слухи, что у Java 9 будет такое исправление, как работающий во времени вариант, но с ошибкой, которая была вокруг в течение многих лет, я сомневаюсь, что она когда-нибудь будет исправлена - особенно учитывая враждебность между Oracle и Google. Любой да, возможно, ошибка действительно глубока в коде Android и должна быть исправлена там. Имея более миллиарда устройств, это не жизнеспособное решение для всех существующих устройств.