Java Сбой сравнения метода - PullRequest
       10

Java Сбой сравнения метода

2 голосов
/ 05 февраля 2020

У меня есть класс с именем task, который я хочу получить в PriorityQueue.

Мой класс сопоставим по date и логическое поле с именем isUrgent

 @Override
        public int compareTo(Task task) {
            int x = 0;
            if (!isUrgent && task.isUrgent)
                x=1;
            else if (isUrgent && !task.isUrgent)
                x=-1;
            else return  date.compareTo(task.date);

            return x +date.compareTo(task.date);
        }

При работе с Comparables в первый раз, когда я удаляю задачу из очереди приоритетов, она должна быть удалена к самой последней дате, но если она срочная, то должна быть удалена первая срочная задача.

Но я получаю это в середине удаления,

Task{isUrgent=true, date=Sat Apr 04 00:00:00 BST 2020}
Task{isUrgent=true, date=Sat Apr 04 00:00:00 BST 2020}
Task{isUrgent=false, date=Sat Apr 04 00:00:00 BST 2020}
Task{isUrgent=true, date=Thu Apr 04 00:00:00 BST 2030}
Task{isUrgent=false, date=Sat Apr 04 00:00:00 BST 2020}
Task{isUrgent=true, date=Thu Apr 04 00:00:00 BST 2030}
Task{isUrgent=false, date=Thu Apr 04 00:00:00 BST 2030}
Task{isUrgent=false, date=Thu Apr 04 00:00:00 BST 2030}

Что я делаю не так в методе сравнения?

Ответы [ 2 ]

4 голосов
/ 05 февраля 2020

То, что вы хотите - сначала сравнить задачи по срочности, а затем по дате. Вместо того, чтобы добавлять результаты двух компараторов, вы должны объединить результаты в цепочку, чтобы даты двух задач сравнивались только в том случае, если их срочность одинакова (т. Е. Оба срочны или оба несрочные).

К счастью, класс Comparator имеет несколько полезных методов, которые облегчают создание компаратора, который делает то, что вы хотите. В большинстве случаев, в том числе в вашем случае использования, вам не нужно на самом деле писать свой собственный метод compareTo. Вы можете использовать метод comparing для сравнения по срочности или дате, и вы можете использовать thenComparing, чтобы связать их вместе. Метод reversed позволяет сравнивать срочности так, чтобы true встречался до false.

Comparator<Task> cmp =
    Comparator.comparing(t -> t.isUrgent).reversed().thenComparing(t -> t.date);

Или с использованием ссылок на методы (если в вашем классе есть методы-получатели):

Comparator<Task> cmp =
    Comparator.comparing(Task::isUrgent).reversed().thenComparing(Task::getDate);

Затем можно создать очередь приоритетов, которая использует этот компаратор, вызвав соответствующий PriorityQueue конструктор :

PriorityQueue<Task> queue = new PriorityQueue<>(cmp);
3 голосов
/ 05 февраля 2020

Вы не придаете достаточный вес своему флагу urgent, возвращая x + date.compareTo(task.date).

Если x равно -1, а результат сравнения дат равен 1, вы вернете ноль .

Кроме того, нет никакой гарантии, что сравнение дат вернет -1, 0 или 1 (хотя предварительные тесты указывают на это). Javado c просто заявляет:

Возвращает:
значение 0, если аргумент Date равен этому Date ; значение меньше 0, если это Date перед аргументом Date; и значение больше 0, если это Date после аргумента Date.

Простое исправление будет:

@Override
public int compareTo(Task task) {
    if (!isUrgent && task.isUrgent)
        return 1;
    else if (isUrgent && !task.isUrgent)
        return -1;

    return date.compareTo(task.date);
}
...