我们应该如何管理空值的jdk8流

2022-08-31 10:21:12

我知道这个主题可能有点,因为JDK8尚未发布(反正现在还没有发布),但我正在阅读一些关于Lambda表达式的文章,特别是与称为Stream的新集合API相关的部分。in advance

以下是Java杂志文章中给出的示例(它是一种水獭种群算法..):

Set<Otter> otters = getOtters();
System.out.println(otters.stream()
    .filter(o -> !o.isWild())
    .map(o -> o.getKeeper())
    .filter(k -> k.isFemale())
    .into(new ArrayList<>())
    .size());

我的问题是,如果在 Set 内部迭代的中间,其中一个水獭为空,会发生什么情况?

我希望抛出一个NullPointerException,但也许我仍然停留在以前的开发范式(非功能性)中,有人可以启发我如何处理这个问题吗?

如果这真的抛出了一个NullPointerException,我发现这个功能非常危险,只能按如下方式使用:

  • 开发人员确保没有空值(可能使用以前的.filter(o -> o != null))
  • 开发人员确保应用程序永远不会生成空水獭或特殊的NullOtter对象来处理。

什么是最佳选择,或任何其他选择?


答案 1

尽管答案是100%正确的,但有一个小建议,用可选来改进列表本身的案例处理:null

 List<String> listOfStuffFiltered = Optional.ofNullable(listOfStuff)
                .orElseGet(Collections::emptyList)
                .stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

该部分将允许您很好地处理空的情况并返回空列表,而不是使用NullPointerException失败。Optional.ofNullable(listOfStuff).orElseGet(Collections::emptyList)listOfStuff


答案 2

斯图尔特的回答提供了一个很好的解释,但我想提供另一个例子。

在尝试对包含空值的流执行时,我遇到了此问题(实际上是 ,这是一种减少)。由于 average() 返回,我假设 Stream 可能包含 null,但相反,一个 NullPointerException 被抛出。这是由于斯图尔特对空 v. 空的解释。reduceLongStream.average()OptionalDouble

因此,正如OP所建议的那样,我添加了一个过滤器,如下所示:

list.stream()
    .filter(o -> o != null)
    .reduce(..);

或者,正如下面所指出的,使用Java API提供的谓词:

list.stream()
    .filter(Objects::nonNull)
    .reduce(..);

来自邮件列表讨论 Stuart 链接:Brian Goetz on null in Streams