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

Java8流-如何正确地使NPE成为安全流

萧献
2023-03-14

上周在一条流中出现了非常奇怪的NPE,这给我带来了很多麻烦,所以现在我觉得在使用流时使用NPE太安全了。

下面是我现在的方法:

private boolean matchSomeError(final List<ErrorAtMessageLevel> errorList) {
    return errorList.stream()
        .filter(errorAtMessageLevel -> errorAtMessageLevel.getErrorSegment() != null && errorAtMessageLevel.getErrorSegment().getErrorDetails() != null)
        .map(errorAtMessageLevel -> errorAtMessageLevel.getErrorSegment().getErrorDetails())
        .anyMatch(errorDetails -> SOME_FANCY_ERROR_CODE.equals(errorDetails.getErrorCode()));
}

我的问题是,我在这里处理的是外部POJO,所以我无法更改它并使其为空安全,所以我必须调整我的代码。

这里有一些限制:1)errorList-此处不能为null,因此调用。stream()是安全的-当它为空时,它只会返回false 2)getErrorSegment()getErrorDetails()都可以为null,这就是为什么我使用这样的过滤器来确保它们都不为null 3)getErrorCode()可以为null,但它永远不会抛出NPE,因为它在匹配时只会返回false我没意见。

你会如何着手让这条小溪变得更好?我觉得我的. filter()很糟糕,可以做得更好。最近写了很多这样的代码,因为我不再确定流是如何使用null的,也不想在. map()中获得NPE,因为它被称为null

共有2个答案

焦阎宝
2023-03-14

我认为写这个的最好方法是定义一个单独的方法,它使用可选来避免空值。然后,您可以在流中使用方法引用引用:

return errorList.stream()
    .map(MyClass::getErrorCode)
    .flatMap(Optional::stream) // from Java 9, else filter then map to Optional.get
    .anyMatch(SOME_FANCY_ERROR_CODE::equals);


private static Optional<String> getErrorCode(final ErrorAtMessageLevel error)
{
    return Optional.ofNullable(error)
        .map(ErrorAtMessageLevel::getErrorSegment)
        .map(ErrorSegment::getErrorDetails)
        .map(ErrorDetails::getErrorCode);
}

方法引用的类名可能不同。您的代码没有显示使用了哪些类,所以我只是使用了合理的猜测。

巩才捷
2023-03-14

您可以通过以下方式更优雅地过滤出nulls:

private boolean matchSomeError(final List<ErrorAtMessageLevel> errorList) {
    return errorList.stream()
        .map(ErrorAtMessageLevel::getErrorSegment)
        .filter(Objects:nonNull)
        .map(ErrorSegment::getErrorDetails)
        .filter(Objects:nonNull)
        .anyMatch(errorDetails -> SOME_FANCY_ERROR_CODE.equals(errorDetails.getErrorCode()));
}
 类似资料:
  • 我正在尝试创建一个简单的解析util,它转换一个两列CSV文件并将其放入一个映射。 如您所见,我正在创建一个字符串流,用逗号分隔每一行,并将其转换为字符串数组,最后将键映射到索引0,将值映射到索引1。 出于某种原因,当我运行这个测试时,实际值为null。我排除了无效的文件路径,因为它在另一个单元测试中运行良好,并且键值出现在CSV中。我已经盯着它看了几个小时了,我想也许有人能指出我的错误。 此外,

  • 我在windows 7机器上安装了JDK 1.7,在安装JDK 1.8 u20后,出现以下错误: 我的变量指向旧版本(即1.7)。 这里出了什么问题,我如何使用java 8和java 7?

  • 我有一连串的弦和空值 我想将它简化为另一个流,其中任何非空字符串序列连接在一起,即像 我发现的第一种方法是创建收集器,首先将完整的输入流减少到具有所有连接字符串列表的单个对象,然后从中创建新流: 但在这种情况下,在任何使用前,如果str2,甚至作为str2。findFirst(),将完全处理输入流。它需要耗费时间和内存的操作,并且在来自某个生成器的无限流上,它将根本不工作 另一种方法-创建将保持中

  • 问题内容: 据我所知,这是可变的,因此,如果多个线程试图访问和修改它,则不是线程安全的。我们如何使用客户端锁定或组合(包装器)使其成为线程安全的? 问题答案: 按照从好到坏的顺序: 根本不使用它,请查看Java 8的新Date and Time API。 完全不使用它,请查看jodatime 在所有的,使用不使用或一成不变的原始与代表 纪元时间 封装它。始终返回的防御性副本,从不引用内部对象 在实

  • 问题内容: 我是Go的新手,我需要创建一个线程安全的变量。我知道在Java中您只能使用关键字,但是似乎没有类似的东西存在。有什么方法可以同步变量? 问题答案: Java中的一种意思是仅允许单个线程(在任何给定时间)执行代码块。 在Go中,有很多构造可以实现该目标(例如互斥体,通道,等待组,中的原语),但是Go的谚语是: “不要通过共享内存进行通信;而是通过通信来共享内存。” 因此,不要锁定和共享变

  • 使用pnpm安装全局http-server,被提示以前设置的淘宝npm源过期了,之前已经更新过registry了,非全局安装npm包时,能够正常使用 但是一旦使用pnpm add -g来全局安装就报错 尝试清除缓存,依旧无法解决问题