如何处理 Java 8 比较器中的空值和重复值?
How do I deal with null and duplicate values in a Java 8 Comparator?
我有一个 Photo
对象:
public class Photo {
@Id
private String id;
private LocalDateTime created;
private Integer poNumber;
}
一组中的部分照片或所有照片的 poNumber 可以为空。我想根据poNumber对一组照片进行排序,让最低的poNumber出现在排序后的集合中。 poNumber 也可以在集合中重复。如果 poNumber 重复,则根据创建的顺序排序(最早创建的照片首先出现)。如果 poNumber 为 null 则根据创建排序。
我试过下面的代码:
Set<Photo> orderedPhotos = new TreeSet<>(
Comparator.nullsFirst(Comparator.comparing(Photo::getPoNumber))
.thenComparing(Photo::getCreated));
for (Photo photo : unOrderedPhotos) {
orderedPhotos.add(photo);
}
但只要 poNumber 为空,它就会抛出 NullPointerException
。如果 poNumber 不为空,则它工作正常。我该如何解决这个问题?
这会将空值放在开头
Integer getPoNumber() { return poNumber == null ? Integer.MIN_VALUE : poNumber };
这会将空值放在末尾
Integer getPoNumber() { return poNumber == null ? Integer.MAX_VALUE: poNumber };
否则,实现您自己的比较器来处理空值
我们需要一个将 Function<>
转换为比较器的解决方案,但以一种将所述 null
检查添加到链中的方式。
这就是 进入场景的地方:它创建一个 Comparator
,将比较的 Photo
映射到 Integer
的比较,然后添加一个比较器,它自然地先将这些 Integer
与 null
一起排序:
Comparator.comparing(Photo::getPoNumber, Comparator.nullsFirst(Comparator.naturalOrder()))
然后这个比较器与另一个考虑创建日期的比较器链接(对于相等的情况)。
按照你写的方式,照片键可以是 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
您可以使用两个参数的 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));
我有一个 Photo
对象:
public class Photo {
@Id
private String id;
private LocalDateTime created;
private Integer poNumber;
}
一组中的部分照片或所有照片的 poNumber 可以为空。我想根据poNumber对一组照片进行排序,让最低的poNumber出现在排序后的集合中。 poNumber 也可以在集合中重复。如果 poNumber 重复,则根据创建的顺序排序(最早创建的照片首先出现)。如果 poNumber 为 null 则根据创建排序。
我试过下面的代码:
Set<Photo> orderedPhotos = new TreeSet<>(
Comparator.nullsFirst(Comparator.comparing(Photo::getPoNumber))
.thenComparing(Photo::getCreated));
for (Photo photo : unOrderedPhotos) {
orderedPhotos.add(photo);
}
但只要 poNumber 为空,它就会抛出 NullPointerException
。如果 poNumber 不为空,则它工作正常。我该如何解决这个问题?
这会将空值放在开头
Integer getPoNumber() { return poNumber == null ? Integer.MIN_VALUE : poNumber };
这会将空值放在末尾
Integer getPoNumber() { return poNumber == null ? Integer.MAX_VALUE: poNumber };
否则,实现您自己的比较器来处理空值
我们需要一个将 Function<>
转换为比较器的解决方案,但以一种将所述 null
检查添加到链中的方式。
这就是 Comparator
,将比较的 Photo
映射到 Integer
的比较,然后添加一个比较器,它自然地先将这些 Integer
与 null
一起排序:
Comparator.comparing(Photo::getPoNumber, Comparator.nullsFirst(Comparator.naturalOrder()))
然后这个比较器与另一个考虑创建日期的比较器链接(对于相等的情况)。
按照你写的方式,照片键可以是 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
您可以使用两个参数的 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));