на compareTo
контракт
Проблема в вашем compareTo
. Вот выдержка из документации :
Исполнитель должен обеспечить sgn(x.compareTo(y)) == -sgn(y.compareTo(x))
для всех x
и y
.
Ваш оригинальный код воспроизводится здесь для справки:
// original compareTo implementation with bug marked
@Override
public int compareTo(Object o) {
int output = 0;
if (boeking.compareTo(((Ticket) o).getBoeking())==0)
{
if(this.equals(o))
{
return output;
}
else return 1; // BUG!!!! See explanation below!
}
else output = boeking.compareTo(((Ticket) o).getBoeking());
return output;
}
Почему return 1;
ошибка? Рассмотрим следующий сценарий:
- Дано
Ticket t1, t2
- Дано
t1.boeking.compareTo(t2.boeking) == 0
- Дано
t1.equals(t2)
Возврат false
- Теперь у нас есть оба из следующих:
t1.compareTo(t2)
возвращает 1
t2.compareTo(t1)
возвращает 1
Последнее последствие - это нарушение контракта compareTo
.
Исправление проблемы
Прежде всего, вы должны были воспользоваться тем, что Comparable<T>
является параметризуемым универсальным типом. То есть вместо:
// original declaration; uses raw type!
public class Ticket implements Comparable
было бы гораздо уместнее объявить что-то вроде этого:
// improved declaration! uses parameterized Comparable<T>
public class Ticket implements Comparable<Ticket>
Теперь мы можем написать наш compareTo(Ticket)
(больше не compareTo(Object)
). Есть много способов переписать это, но вот довольно упрощенный, который работает:
@Override public int compareTo(Ticket t) {
int v;
v = this.boeking.compareTo(t.boeking);
if (v != 0) return v;
v = compareInt(this.rijNr, t.rijNr);
if (v != 0) return v;
v = compareInt(this.stoelNr, t.stoelNr);
if (v != 0) return v;
v = compareInt(this.ticketType, t.ticketType);
if (v != 0) return v;
return 0;
}
private static int compareInt(int i1, int i2) {
if (i1 < i2) {
return -1;
} else if (i1 > i2) {
return +1;
} else {
return 0;
}
}
Теперь мы можем также определить equals(Object)
в терминах compareTo(Ticket)
, а не наоборот:
@Override public boolean equals(Object o) {
return (o instanceof Ticket) && (this.compareTo((Ticket) o) == 0);
}
Обратите внимание на структуру compareTo
: она имеет несколько операторов return
, но на самом деле поток логики вполне читабелен. Обратите также внимание на то, что приоритет критериев сортировки является явным и легко переставляемым, если вы имеете в виду различные приоритеты.
Смежные вопросы