假设您有一个包含空值的整数列表
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声明它是无效的? 那么对包含空值的整数列表进行排序的最佳方法是什么?
感谢您的想法!
答案 0 :(得分:3)
Stream#max
州的文件:
抛出:NullPointerException - 如果最大元素为null
由于您提供了一个将null
视为最大元素的比较器,因此它会抛出异常。
这是堆栈跟踪在您的示例中尝试返回Optional.of(state);
state
为null
时指示的内容,如果传递的值为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
。