当前位置: 首页 > 知识库问答 >
问题:

为什么Stream.Reduce(BinaryOperator)在结果为Null时抛出NullPointer?

樊运乾
2023-03-14

我有一个想要减少的枚举值流。如果流为空或包含不同的值,我希望null。如果它只包含一个值(的多个实例),我想要那个值。

[]              null
[A, B, A]       null
[A]             A
[A, A, A]       A

我试着用减音来做:

return <lots of filtering, mapping, and other stream stuff>
       .reduce((enum1, enum2) -> enum1 == enum2 ? enum1 : null)
       .orElse(null);

不幸的是,这不起作用,因为当结果为null时,这个reduce方法抛出一个nullPointerException。有人知道为什么会这样吗?为什么null不是有效的结果?

现在,我是这样解决的:

MyEnum[] array = <lots of filtering, mapping, and other stream stuff>
                 .distinct()
                 .toArray(MyEnum[]::new);
return array.length == 1 ? array[0] : null;

在这起作用的同时,我并不满足于这种“弯路”。我喜欢减少,因为它似乎是合适的,把所有的东西都放进一个流。

有没有人能想出一个替代reduce的方法(理想情况下不需要太多代码)?

共有1个答案

上官季
2023-03-14

通常,所有返回optional的流方法都不允许null值,因为无法区分null结果和“无结果”(空流)。

您可以使用占位符值来解决这一问题,不幸的是,这需要挂起类型安全(因为枚举集之外没有与类型兼容的值):

return <lots of filtering, mapping, and other stream stuff>
    .reduce((enum1, enum2) -> enum1 == enum2? enum1: "")
    .map(r -> r==""? null: (MyEnum)r)
    .orElse(null);

如果映射函数返回nulloptional.map将返回一个空的optional.map。因此,在该步骤之后,空流和null结果将无法区分,并且orelse(null)在这两种情况下都将返回null

但是也许数组绕道只是感觉不满意,因为数组不是中间结果的最佳选择?怎么样

EnumSet<MyEnum> set = <lots of filtering, mapping, and other stream stuff>
    .collect(Collectors.toCollection(() -> EnumSet.noneOf(MyEnum.class)));
return set.size()==1? set.iterator().next(): null;

如果enum类型的常数不超过64个,则enumset只是一个位集,即单个long值。这比数组便宜得多,而且由于set自然是不同的,因此不需要对流执行distinction()操作,这会在底层创建hashset

 类似资料:
  • 对于我的具体情况,我想在约简中使用函数合成;例如: 这有一个编译错误: 相反,我需要做的是: 但是,这就失去了composition提供的无点样式。 为什么流API是这样设计的?是,所以用超类型声明方法的参数不是更有意义吗?

  • 问题内容: 根据文档,该方法返回: 如果参数是,则字符串等于; 否则,返回的值。 但是,当我尝试这样做时,怎么会这样: 它会抛出NPE吗?(如果你不相信,请自己尝试!) 怎么会这样呢?文件在骗我吗?这是Java中的主要错误吗? 问题答案: 问题是方法已重载: String.valueOf(Object) String.valueOf(char[]) Java规范语言要求在这种情况下,选择最具体的重

  • 问题内容: 运行此命令时: 响应为: 这对我来说真是太棒了。我本以为这会带来编译时错误。 为什么我可以在Java中抛出null,为什么将其转换为NullPointerException? (实际上,鉴于我抛出的是null,因此我不知道这是否是“ upcast”) 除了一个非常愚蠢的面试问题(请没人在面试中问这个问题)之外,我看不到任何理由。也许您想被解雇,但这就是…我的意思是,为什么还会有人呢?

  • 我有一段类似这样的代码: 我的测试是: 上面的代码不应该抛出NPE吗? 当我将测试更改为: 然后我的代码正确地抛出了一个空指针异常。 我的测试第一版和第二版有什么区别? 在我的第一个版本中,我告诉mockA返回mockB。但是我也将mockB设置为null,所以当调用b.doSomething()时,我认为该方法应该抛出一个空指针,因为它试图调用null.doSomething()。 我知道我应该

  • 因为场景2(for-each循环)运行良好,但是场景1(map.entry::getValue)和场景3(e->e.getValue())都抛出了NPE。 为什么toMap有这个问题,而在哈希映射的概念中,键和值都允许为空? 请解释一下。

  • 我创建了一个从HashMap中删除学生的方法。当id为NULL时,它会抛出一个异常。有人知道它为什么不起作用吗? 公共类应用程序{public static void main(String[]args){ }