上周在一个流中遇到了非常奇怪的 NPE,这给我带来了很多麻烦,所以现在我觉得在使用 Stream 时对 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 - 此处不能为空,因此调用 .stream() 是安全的 - 当它为空时,它只会返回 false
2) getErrorSegment()getErrorDetails() 都可以是空值,这就是为什么我使用这样的过滤器来确保它们都不是空值
3) getErrorCode() 可以为 null 但它永远不会抛出 NPE 因为它在与 null 匹配时只会返回 false - 我很好。

您将如何使该流变得更好?我觉得我的 .filter() 很糟糕,可以做得更好。最近写了很多这样的代码,因为我不再确定流是如何处理空值的,并且不想在 .map() 中获得 NPE,因为它是在空值上调用的

最佳答案

您可以通过这种方式更优雅地过滤 null :

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()));
}

关于Java 8 流 - 如何正确制作 NPE 安全流,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53040979/

10-13 23:42