如何处理 Java 8 比较器中的空值和重复值?

2022-09-04 01:28:52

我有一个对象:Photo

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

对于某些照片或集合中的所有照片,poNumber 可以为 null。我想根据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);
}

但是每当 poNumber 为 null 时,它就会抛出一个。如果 poNumber 不为空,则它工作正常。我该如何解决这个问题?NullPointerException


答案 1

我们需要一个解决方案,将 转换为比较器,但以一种将所述检查添加到链中的方式。Function<>null

这就是Oleksandr的答案进入场景的地方:它创建了一个将比较映射到s的比较,然后添加一个比较器,该比较器自然地将这些与s排序为第一个:ComparatorPhotoIntegerIntegernull

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

然后,该比较器(对于相等的情况)与另一个考虑创建日期的比较器链接在一起。


答案 2

您可以使用双参数比较器。比较重载,例如:

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

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

推荐