Сортировка таблицы с помощью компаратора, который «закрепляет» элементы вверху

#java #logic #comparator

#java #Логические #компаратор

Вопрос:

У меня есть пользовательская таблица, использующая компаратор для сортировки элементов по столбцам. Я хочу «закрепить» определенные элементы вверху, независимо от текущей сортировки (asc / desc). Помимо «обычных» элементов (C), которые сравниваются как обычно, у меня также есть один специальный элемент (A), который всегда должен быть в верхней части таблицы, и N «избранных» элементов (B), которые должны быть после A и перед C, и их порядок не важен (но я также попытался «отсортировать» их на основе их числового значения).

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

 A (always present on top)
B (isFavorite)
B (isFavorite)
C (these items are sorted normally)
C
...
C
  

Вот мой компаратор, который не работает должным образом. Иногда A идет после B или я даже получаю Comparator violates general contract исключение.

 private class CustomOrderAwareComparator implements Comparator<MyObject> {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        // isA() is always true only for one item
        if(o1.isA() amp;amp; o2.isA())
            return 0;
        else if(o1.isA())
            return table.getSortedOrder() == DESCENDING ? 1 : -1;

        // isB() can be true for multiple items
        if(o1.isB() amp;amp; o2.isB()))
            return 0;
        else if(o1.isB())
            return table.getSortedOrder() == DESCENDING ? 1 : -1;

        return o1.getValue().compareTo(o2.getValue());
    }
}
  

Я был бы признателен за любую информацию о том, чего мне здесь не хватает. Спасибо!

Комментарии:

1. это то, что отсутствует else if условие для o2.isA()

2. что такое e2 ошибка копирования и вставки? и что более важно, что произойдет, если o2 это A ? или B ? (для упорядочивания, когда оба A (или B ) просто возвращают результат из compareTo вместо нуля)

3. @CarlosHeuberger да, я исправил пример. A гарантированно будет только одним. В любом наборе элементов всегда будет только один A.

4. не отвечает «что, если o2 есть A ?» — вы не тестируете случай, когда o2 (только) это один A элемент, вы только проверяете o1 — вам нужно что-то вроде if (o2,isA()) return ... {то же самое для if (o2.isB()) ... }

5. @CarlosHeuberger спасибо, это помогло! Я добавил эти проверки, и теперь это работает.

Ответ №1:

Я думаю, что после else if (o1.isA()) return... вам также нужно else if (o2.isA()) return table.getSortedOrder() == DESCENDING ? -1 : 1; . Сделайте то же самое для B . В противном случае некоторые из As и некоторые из Bs могут не пройти getValue() проверку.

Это может исправить общее нарушение контракта, но вам может потребоваться обновить ваш equals метод, чтобы соответствовать поведению compare .

Комментарии:

1. на самом деле else не требуется, поскольку return вводится в каждый if блок

2. Да, добавление этих двух else if помогло и теперь работает должным образом. Спасибо! Не уверен, следует ли все еще переопределять equals сейчас, поскольку все уже работает? Какой случай это разрешило бы?

3. Прохладный. Ошибка контракта, вероятно, произошла, когда коллекция, использующая компаратор для сортировки, заметила, что метод equals не соответствует методу compare. Типичный метод equals, сгенерированный IDE, скорее всего, соответствует вашему фиксированному методу сравнения.