Как мне работать с нулевыми и дублирующимися значениями в компараторе Java 8? - PullRequest
0 голосов
/ 16 ноября 2018

У меня есть Photo объект:

public class Photo {
    @Id
    private String id;
    private LocalDateTime created;
    private Integer poNumber;
}

poNumber может быть нулевым для некоторых фотографий или всех фотографий в наборе.Я хочу отсортировать набор фотографий в соответствии с poNumber, чтобы наименьшее значение poNumber появилось первым в отсортированном наборе.poNumber также может дублироваться в наборе.Если poNumber дублируется, то сортируйте в соответствии с созданным (самое раннее созданное фото появляется первым).Если poNumber равен нулю, то сортировать в соответствии с созданным.

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

Set<Photo> orderedPhotos = new TreeSet<>(
    Comparator.nullsFirst(Comparator.comparing(Photo::getPoNumber))
              .thenComparing(Photo::getCreated));

for (Photo photo : unOrderedPhotos) {
    orderedPhotos.add(photo);
}

Но он выдает NullPointerException всякий раз, когда poNumber равен нулю.Если poNumber не равен нулю, он работает нормально.Как я могу решить эту проблему?

Ответы [ 4 ]

0 голосов
/ 16 ноября 2018

Вы можете использовать перегрузку с двумя аргументами Comparator.comparing , например:

import static java.util.Comparator.*; // for the sake of brevity

Set<Photo> orderedPhotos = new TreeSet<>(
    Comparator.comparing(Photo::getPoNumber, nullsFirst(naturalOrder()))
              .thenComparing(Photo::getCreated));
0 голосов
/ 16 ноября 2018

Нам нужно решение, которое превращает Function<> в компаратор, но таким образом, чтобы добавить упомянутую проверку null в цепочку.

И вот тут Ответ Александра выходит на сцену: он создает Comparator, который отображает сравниваемые Photo на сравнение Integer с, а затем добавляет Comparator, который естественным образом упорядочивает эти Integer s с null s первым:

Comparator.comparing(Photo::getPoNumber, Comparator.nullsFirst(Comparator.naturalOrder()))

И этот компаратор затем связывается (для случая равенства) с другим компаратором, который рассматривает дату создания.

0 голосов
/ 16 ноября 2018

Как вы и написали, ключ Фото может быть null, но не более.

Comparator.nullsFirst( // Photo could be null.
    Comparator.comparing(Comparator.nullsFirst(Photo::getPoNumber)) // poNumber could be null.
              .thenComparing(Comparator.nullsFirst(Photo::getCreated))) // created could be null

Если какой-либо из них не может быть null, вы можете удалить Comparator.nullsFirst

0 голосов
/ 16 ноября 2018

Это установит нулевые значения в начале

Integer getPoNumber() { return poNumber == null ? Integer.MIN_VALUE : poNumber };

Это установит нулевые значения в конце

Integer getPoNumber() { return poNumber == null ? Integer.MAX_VALUE: poNumber };

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

...