Почему я получаю «Метод сравнения нарушает его общий контракт»

1

если я назову эту строку кода

Arrays.sort(allNew, 0, sizeNew, mCatBPosComparator);

с этим компаратором

 private class BPosComparator implements Comparator<CatBPos> {

    private static final int SWAP_BPosS = 1;

    @Override
    public int compare(CatBPos p1, CatBPos p2) {
      int lCompare;

      if (TimeUtils.isNotVoid(p1.getHdopBPos().getTime()) && TimeUtils.isNotVoid(p2.getHdopBPos().getTime())) {
        lCompare = p1.getHdopBPos().getTime().compareTo(p2.getHdopBPos().getTime());
        if (lCompare != 0) {
          return lCompare;
        }
      }

      lCompare = p1.getBPos().getTime().compareTo(p2.getBPos().getTime());
      if (lCompare != 0) {
        return lCompare;
      }

      if (p1.getBPos().isDeparture() && p2.getBPos().isVacation()) {
        return SWAP_BPOS;
      } else if (p1.getBPos().isVacation() && p2.getBPos().isArrival()) {
        return SWAP_BPOS;
      }

      // Ankunft und Abfahrt für denselben Bahnhof sollen in der richtigen Reihenfolge sein
      if (p1.getBPos().isDeparture() && p2.getBPos().isArrival() && p1.getBPos().getStat().equals(p2.getBPos().getStat())) {
        return SWAP_BPOS;
      }

      return 0;
    }
  }

Я сталкиваюсь с этим Исключением:

Comparison method violates its general contract!

Я вижу много вопросов по этому поводу. Но я этого не понимаю. Не могли бы вы помочь мне?

  • 0
    Это исключение обычно означает, что существуют три объекта A, B и C, так что A> B, B> C и A <= C. «Возврат 0» внизу крайне подозрительный, поскольку он сообщает об элементах как о равных когда набор разработанных критериев не выполняется.
Теги:
comparator

4 ответа

4
Лучший ответ

Я подозреваю, что это, по крайней мере, одна непосредственная проблема:

if (p1.getBPos().isDeparture() && p2.getBPos().isVacation()) {
    return SWAP_BPOS;
} else if (p1.getBPos().isVacation() && p2.getBPos().isDeparture()) {
    return SWAP_BPOS;
}

Если вы вызываете compare(p1, p2) а затем compare(p2, p1) вы получите тот же ненулевой результат... который нарушает правила сравнения.

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

Вы можете начать с отрицания SWAP_BPOS для обратной ситуации:

if (p1.getBPos().isDeparture() && p2.getBPos().isVacation()) {
    return SWAP_BPOS;
} else if (p1.getBPos().isVacation() && p2.getBPos().isDeparture()) {
    return -SWAP_BPOS;
}

Это может быть не все, что нужно, но это начало.

  • 0
    ээээ ... хорошо ... позвольте мне проверить это ...
  • 0
    Уважаемый Джон. Я сделал ошибку копирования и вставки, создав этот вопрос. пожалуйста, смотрите мой отредактированный код. Я думаю, что с обновленным кодом вышеупомянутая часть не должна быть проблемой.
Показать ещё 3 комментария
1

Вы должны убедиться, что ваш оператор сравнения подчиняется всем соответствующим математическим правилам:

  1. Если A <B и B <C, то A <C.
  2. Если A <B, то B> A.
  3. Если A == B, то B == A.

В частности, обратите внимание на код, который может возвращать тот же порядок/результат для противоположных входов. Ваше сравнение должно быть в состоянии окончательно заказать ваши товары.

По моему опыту, ошибки в пункте 2 кажутся наиболее распространенной ошибкой.

  • 1
    1) транзитивный и 2,3) симметричный и рефлексивный вы забыли xD
  • 0
    @nachokk Рефлексивное равенство подразумевается 2 (если аргументы идентичны, но результат "не равен", то 2 должен быть нарушен, когда аргументы меняются местами). См. Также Comparator.compareTo , который соответствует этим правилам.
0

Оператор сравнения должен быть транзитивным. Короче говоря, это означает, что вы должны определить его таким образом, что если a.compareTo(b) отрицательный, а b.compareTo(c) отрицательный, то a.compareTo(c) также является отрицательным. Это несколько интуитивно - если a меньше b и b меньше c, то a меньше c. Также вы должны убедиться, что если a.compareTo(b) равно нулю, чем b.compareTo(a) равно нулю, т.е. если a равно b, то b равно a.

  • 0
    Ваша вторая точка и одна отсутствующая точка могут быть объединены и обобщены как sign(a.compareTo(b)) = -sign(b.compareTo(a)) - помните, a.compareTo(b) должен давать противоположный порядок b.compareTo(a) if a!=b ; это одна из самых распространенных ошибок при реализации.
  • 0
    Да, но я старался быть более многословным, чтобы быть более ясным.
0

В принципе, ваш метод сравнения должен быть последовательным. Если A> B и B> C, то A должно быть больше C. Вероятно, ваш код там не работает.

  • 0
    Если A > B и B > C , предполагается, что A > C , а не наоборот.
  • 0
    Вы правы. Извините за опечатку.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню