Java 8 - 排序带空值的整数列表

时间:2017-10-04 09:16:37

标签: sorting null java-8

假设您有一个包含空值的整数列表

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()));

如果您认为空值小于非空值,则它有效。但是如果你希望它们更大并且将nullsFirst更改为nullsLast

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

然后你会再次遇到NullPointerException。

我很有意思 - 为什么nullsLast在这种情况下不起作用,因为它的doc声明它是无效的? 那么对包含空值的整数列表进行排序的最佳方法是什么?

感谢您的想法!

3 个答案:

答案 0 :(得分:3)

Stream#max州的文件:

  

抛出:NullPointerException - 如果最大元素为null

由于您提供了一个将null视为最大元素的比较器,因此它会抛出异常。

这是堆栈跟踪在您的示例中尝试返回Optional.of(state); statenull时指示的内容,如果传递的值为Optional.of则抛出NPE null

Comparator.nullsLast工作正常,例如:

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

确实会给你null

答案 1 :(得分:2)

如果您认为null大于任何非null值,则当列表包含任何null时,最大值为null

由于Stream.max已经记录了当结果为NullPointerException时它会抛出null,这是预期的行为。设计原理与findFirst()类似,已在this 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还是根本没有元素。

答案 2 :(得分:1)

那不是关于Comparator本身:

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

您将空值放在最后,那将是max;在max的null抛出上调用NullPointerException