Какой класс выбрасывает исключение IllegalArgumentException при сортировке с JRE 1.7?

Меня поразило (по-видимому, пресловутое) IllegalArgumentException, используя Collections.sort() в Java7 Благодаря SO я понимаю причину, которая в основном (кашель) плохой код. Дело в том, что я не могу воспроизвести Исключение самостоятельно. Я сделал некоторый кодовой поиск исходного кода jdk и нашел, какой класс бросает это исключение. Идея состоит в том, чтобы создать соответствующий тестовый пример. Вот код, кстати, < уровень гордости="0">

@Override
public int compareTo( Symbol other) {
 if( this.lastUse == 0) {
 if( other.lastUse != 0) return (int)( -DateMicros.ONE_DAY);
 } else if( other.lastUse == 0) {
 return ( int)DateMicros.ONE_DAY;
 }
 return ( int)( this.lastUse - other.lastUse);
}

Вдобавок к этому, "lastUse" получает назначенные временные метки в микросекундах и миллисекундах (да смешанные), что дает превосходную утечку переполнения int Реальный вопрос: Какие значения сделают этот кодекс сбоем?, чтобы получить правильный тестовый пример по дороге.

Обновление с трассировкой стека:

at java.util.ComparableTimSort.mergeHi(Unknown Source)
at java.util.ComparableTimSort.mergeAt(Unknown Source)
at java.util.ComparableTimSort.mergeCollapse(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at java.util.Collections.sort(Unknown Source)
3 ответа

Трудно сказать, не глядя на сам стек.

Но docs упоминает, что сам метод может генерировать исключение.

(необязательно), если реализация обнаруживает, что естественный порядок элементов списка обнаруживает нарушение договора сравнения

Обновление

Похоже, что ваш объект не выполняет требования к последовательности Comparable:

Естественное упорядочение для класса C называется согласованным с равенствами тогда и только тогда, когда e1.compareTo(e2) == 0 имеет то же булево значение, что и e1.equals(e2) для всех e1 и e2 класса C Обратите внимание: null не является экземпляром какого-либо класса, а e.compareTo(null) должен вызывать исключение NullPointerException, даже если e.equals(null) возвращает false.


Похоже, что авария вызвана переполнением целых чисел, которое, однако, не должно было быть. Это было определено как ошибка, и это также дает вам путь.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7075600

Попробуйте это как временное исправление:

Adding -Djava.util.Arrays.useLegacyMergeSort=true to my eclipse.ini does seem to have resolved the issue.

Вы можете найти это исправление в той же самой ссылке, которую я опубликовал.

Также посетите этот http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6923200, который был тем же самым сообщением, сообщенным до первой ссылки, однако он был закрыт, так как они не смогли повторно создать такую ​​же проблему.


От Java SE 7 и JDK 7 Совместимость

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

Сводка: Обновленное поведение сортировки для массивов и коллекций может вызвать исключение IllegalArgumentException

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

RFE: 6804124

Таким образом, правильная реализация должна выглядеть как

public int compareTo( Symbol other) {
 if( this.lastUse == other.lastUse) {
 return 0;
 } else if( other.lastUse>this.lastUse) {
 return 1;
 }
 return -1;
 }

Ссылки

licensed under cc by-sa 3.0 with attribution.