2015-12-17 3 views
1

Мы написали следующий код, который не работает для метода Comparator.Компаратор не работает

public int compare(Object o1, Object o2) 
{ 
    if (o2 == null) return 1; 
    else if (o1 == null) return -1; 

    MailObject a = (MailObject)o1; 
    MailObject b = (MailObject)o2; 
    return a.getType() < b.getType()? 1 : -1; 
} 

, где метод getType() возвращает целочисленное значение. и следующий код работает отлично

public int compare(Object o1, Object o2) 
{ 
    if (o2 == null) return 1; 
    else if (o1 == null) return -1; 

    MailObject a = (MailObject)o1; 
    MailObject b = (MailObject)o2; 
    return a.getType() - b.getType(); 
} 

Если удалить тройной оператор в обратном заявлении, то он работает нормально. Если мы добавим равную проверку, то и она работает нормально. Зачем?

первый блок кода подачи следующее исключение:

07:45:22 ERROR c.c.servlet.MyServlet - Comparison method violates its general contract! 
java.lang.IllegalArgumentException: Comparison method violates its general contract! 
       at java.util.TimSort.mergeHi(Unknown Source) ~[na:1.8.0_25] 
       at java.util.TimSort.mergeAt(Unknown Source) ~[na:1.8.0_25] 
       at java.util.TimSort.mergeCollapse(Unknown Source) ~[na:1.8.0_25] 
       at java.util.TimSort.sort(Unknown Source) ~[na:1.8.0_25] 
       at java.util.Arrays.sort(Unknown Source) ~[na:1.8.0_25] 
       at java.util.List.sort(Unknown Source) ~[na:1.8.0_25] 
       at java.util.Collections.sort(Unknown Source) ~[na:1.8.0_25] 
+0

Какую ошибку вы получаете? А что такое класс MailObject? – proudandhonour

+0

Зачем вам нужен тройной оператор? – Munyari

+0

** Почему вы не набираете свой компаратор прямо? ** – Makoto

ответ

7

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

Вместо того, чтобы пытаться реализовать логику сравнения между двумя целыми числами, почему бы не позволить Integer сделать what it knows best?

return Integer.compare(a.getType(), b.getType()); 
+0

Можем ли мы иметь что-то подобное для аргументов с нулевым значением? – Basilevs

+0

Можете ли вы объяснить, какой контракт в основном между интерфейсом Comparator и нашей реализацией. –

+0

@Basilevs в Java 7 и ниже, я просто обрабатываю 'null' явно, как OP. В Java 8 и выше у вас есть синтаксический сахар для этого с помощью 'Comparator.nullsFirst' и' Comparator.nullsLast'. – Mureinik

0

Вы забыли вернуть 0 при равных значениях.

После всегда верно для ненулевых х:

(x < x ? 1 : -1) == -1 
+0

Предполагая, что 'a.getType' возвращает' int'; 'a.getType() - b.getType()' будет возвращать 0, если их результаты эквивалентны. – Makoto

+0

Как насчет трёхмерного оператора? – Basilevs

0

Оба ваших компаратора НЕ совпадают, они фактически противоположны друг другу.

В первом случае, если a меньше, вы возвращаете положительное значение.

Во-вторых, если a меньше, вы возвращаете отрицательное значение.

0

Вы можете попробовать следующий код, который учитывал бы, если они равны, чего не будет. Он будет возвращать -1, если они равны или b больше, чем a. Так что попробуйте ...

return a.getType() < b.getType()? -1: a.getType()> b.getType()? 1: 0;

В этом случае он проверяет, если a меньше, чем b, если оно есть, оно возвращает -1, если это не так, тогда оно проверяет, если a больше b, если это правда, оно возвращает 1, если не они должен быть равен, чтобы он возвращал 0;

Конечно, вы можете изменить эти значения на то, что вам подходит.

Смежные вопросы