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

处理空指针并在流中引发异常

孔飞舟
2023-03-14

让我们考虑一个<代码>父< /代码>类,它只包含一个<代码>整数< /代码>属性。我用一个空变量创建了6个父类对象。然后我将这些对象添加到列表中。

我想通过Integer属性的值检索相应的对象。我使用了Java8流。

Predicate<Parent> predicate = e -> e.getId() == 100; // sample attribute value
result = list.stream().filter(predicate).collect(Collectors.toList());

但是我得到了NullPointerException,所以我编辑了代码:

list.stream().filter(h -> h!=null).filter(predicate).collect(Collectors.toList());

但是如果任何对象为null,我想抛出一个异常。如果列表中没有对象为null,那么我想从列表中检索相应的对象。

如何使用Java 8 Streams使用一条语句实现这一点?

共有3个答案

阳兴文
2023-03-14

在生产代码中使用Stream#map,不要使用Stream#peek方法。正如Javadoc所说,peek主要是为了支持调试。。。流实现能够优化的地方。。。,不会为这些元素调用该操作 参考:javadoc

  list.stream()
      .map(Objects::requireNonNull)
      .filter(predicate)

这段代码清楚地将验证部分和过滤部分分开。它将在异常调用堆栈中包含“要求非空”帧。尽管,根据java.util设计,它将上升NPE异常类型。参考: javadoc。SRC: openjdk

  list.stream()
      .map(item -> requireNonNull(item, "Null item in the list."))
      .filter(predicate)

导入静态java。util。物体。requirennull;

参考:javadoc。SRC:openjdk

  list.stream()
      .map(item -> requireNonNull(item, () -> "Expected non-null items. Was: " + list))
      .filter(predicate)

参考:javadoc。SRC:openjdk

  list.stream()
      .map(this::requireItemNonNull)
      .filter(predicate)
      ...


private Parent requireItemNonNull(Parent item) {
  if (null == item) throw new IllegalStateException("Expected: non null items. Was: " + this.list);
  return item;

如果只需要验证所有项目,请在最后使用收集器。例如,toArray,因为流将实际迭代推迟到“收集”时间:

  list.stream()
      .map(this::validateItemNonNull)
      .toArray();
诸新霁
2023-03-14

让我们从最简单的解决方案开始:

if(list.contains(null)) throw new MyException();
result = list.stream().filter(predicate).collect(Collectors.toList());

如果您怀疑列表包含nulls,甚至有专门的异常类型来标记这种情况,那么预检查是最干净的解决方案。这确保了当谓词更改为可以处理nulls的内容时,或者当您使用短路流操作时,这种情况不会悄悄地保持,该操作可能会在遇到后续null之前结束。

如果列表中出现的null仍然被认为是不应该发生的编程错误,但是您只想更改异常类型(我无法想象这样做的真正原因),您可以捕获并翻译异常:

try {
    result = list.stream().filter(predicate).collect(Collectors.toList());
}
catch(NullPointerException ex) {
    if(list.contains(null)) // ensure that we don’t hide another programming error
        throw new MyException();
    else throw ex;
}

在假定不发生null引用的情况下,这是有效的。如前所述,如果您怀疑列表中包含null,则应该进行预检查。

闽康安
2023-03-14

JB Nizet的答案是可以的,但它使用map只是为了它的副作用,而不是映射操作,这有点奇怪。当你只对某件事的副作用感兴趣时,可以使用一种方法,比如抛出一个异常:peek

List<Parent> filtered = list.stream()
    .peek(Objects::requireNonNull)
    .filter(predicate)
    .collect(Collectors.toList());

如果你想要自己的例外,只需在里面放一个lambda:

List<Parent> filtered = list.stream()
    .peek(p -> { if (p == null) throw new MyException(); })
    .filter(predicate)
    .collect(Collectors.toList());

如果您的异常被选中,您可以事先检查是否为null,如果您不介意遍历列表两次的话。这可能对您的情况最好,但可能并不总是可能的。

if (list.contains(null)) throw new MyCheckedException();

您还可以在流管道中抛出未经检查的异常,捕获它,然后抛出已检查的异常:

try {
    ...
        .peek(p -> { if (p == null) throw new MyException(); })
    ...
} catch (MyException exc) {
    throw new MyCheckedException();
}

或者你可以选择优雅但有争议的方式,使用一种偷偷摸摸的投掷方法。

但要当心!这种技术绕过了检查异常系统,您应该知道自己在做什么。确保声明周围的方法抛出MyCheckedException!如果不这样做,编译器将不会警告您,如果检查异常出现在预期之外的地方,则可能会导致奇怪的错误。

@SuppressWarnings("unchecked")
public <T extends Throwable> void throwSneakily(Throwable t) throws T {
    throw (T) t;
}

public void m() throws MyCheckedException {
    List<Parent> filtered = list.stream()
        .peek(p -> { if (p == null) throwSneakily(new MyCheckedException()); })
        .filter(predicate)
        .collect(Collectors.toList());
}
 类似资料:
  • 第一个示例:“源代码”https://ci.apache.org/projects/flink/flink-docs-stable/dev/stream/operators/process_function.html“” 我正在尝试重写KeyedProcessFunction类的processElement()。ProcessElement有3个参数,其中一个参数是上下文对象。当我试图从上下文对象

  • 我正在尝试通过Maven运行cucumber+testng+selenium。 当我在Eclipse中通过TestNG测试运行它时,它工作得很好,但当我使用mvn测试时,它会抛出空指针异常 我是不是漏掉了什么?

  • 当我们尝试用Null值获取数据时 IN子句获得空指针异常。 也许是因为这个。 在数据库中,我们可以提供null in IN子句。 jooq中存在一个“无法修复”的问题https://github.com/jOOQ/jOOQ/issues/3867 有一些替代方案: 在输入前检查null(在我的情况下,这是一个非常大的select语句) 所以如果我想让这成为可能,还有其他的解决方法吗。 注:类似的情

  • 本文向大家介绍浅谈java异常处理之空指针异常,包括了浅谈java异常处理之空指针异常的使用技巧和注意事项,需要的朋友参考一下 听老师说,在以后的学习中大部分的异常都是空指针异常。所以抽点打游戏的时间来查询一下什么是空指针异常 一:空指针异常产生的主要原因如下: (1)当一个对象不存在时又调用其方法会产生异常obj.method() // obj对象不存在 (2)当访问或修改一个对象不存在的字段时

  • 我正在Kura/osgi网站上的“Hello World Example”上开发我的第一个osgi包。 当我想按所述导出项目(导出-可部署插件和片段)时,我会得到以下结果: “导出插件”期间发生内部错误。java.lang.NullPointerException 不幸的是,没有更多的信息。 这似乎与这里描述和“解决”(?)相同,但我真的不知道该怎么做才能解决问题。我正在使用:Win 7(64),

  • 我正在研究leetcode问题编号876,其中表示: 给定一个非空的、带有头节点头的单链表,返回链表的一个中间节点。如果有两个中间节点,则返回第二个中间节点。 到目前为止,这就是我写的,但是它在时循环中抛出了一个空指针异常。我想既然时循环每次都在做任何事情之前检查node.next.next是否为空,它就不会抛出异常。我做错了什么?