Java 8 - 对有空值的整数列表进行排序

3
假设你有一个整数列表,其中包含null值。
List<Integer> integers = Arrays.asList(null, 9, 11, 7, 5, null);

现在,如果您想获取最大值,可以尝试使用

OptionalInt max = integers.stream()
        .mapToInt(Integer::valueOf)
        .max();

如果列表不包含空值,这个方法就能够正常工作。但在我们的情况下,会出现NullPointerException异常。经过一番研究,我找到了以下解决方案:

Optional<Integer> max = integers.stream()
        .max(Comparator.nullsFirst(Comparator.naturalOrder()));

如果您认为 null 值小于非 null 值,则此方法可行。但如果您想要 null 值更大,并将 nullsFirst 更改为 nullsLast。
Optional<Integer> max = integers.stream()
        .max(Comparator.nullsLast(Comparator.naturalOrder()));

那么您将再次遇到NullPointerException异常。

我很感兴趣 - 为什么在这种情况下nullsLast不起作用,考虑到它的文档声明它是对null友好的?那么对于包含null的整数列表,最佳排序方法是什么?

谢谢您的想法!


考虑更改此问题的名称。它与排序无关,是吗? - Erk
3个回答

4

这并不是关于Comparator本身的问题:

List<Integer> result = integers.stream()
            .sorted(Comparator.nullsLast(Comparator.naturalOrder()))
            .collect(Collectors.toList());
System.out.println(result); // [5, 7, 9, 11, null, null]

你正在将你的 null 值放到末尾,那就是“max”;对 null 调用“max”会抛出“NullPointerException”。

3
Stream#max 的文档说明:

若最大值为空,则抛出 NullPointerException 异常

在您提供将 null 视为最大值的比较器时,因此它会抛出异常。

在您的示例中,当尝试使用 null 值返回 Optional.of(state) 时,栈跟踪指示了这一点,并且如果传递的值是 null,则 Optional.of 将抛出 NPE 异常。

例如,Comparator.nullsLast 可以正常工作:

Integer max = 
    Collections.max(integers, Comparator.nullsLast(Comparator.naturalOrder()));

如果没有正确初始化变量,它确实会返回null


2
如果您认为null比任何非null值都要大,那么当列表包含任何null时,最大值当然将是null
由于Stream.max已经记录了当结果为null时会抛出NullPointerException,因此这是预期的行为。设计理念类似于findFirst(),这在这个Q&A中已经讨论过。
请注意,即使
Optional<Integer> max = integers.stream()
    .max(Comparator.nullsFirst(Comparator.naturalOrder()));

仍然可能失败,即如果所有值都是null。 但在这里使用自定义Comparator没有意义,因为解决方案很简单:

OptionalInt max = integers.stream()
    .filter(Objects::nonNull)
    .mapToInt(Integer::valueOf)
    .max();

当你得到一个空的OptionalInt时,你仍然可以测试integers.isEmpty()来确定是否所有元素都是null或者根本没有元素。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接