上周在流中出现了非常奇怪的NPE,这引起了我的很多麻烦,所以现在我感觉使用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,所以我无法更改它并使它为null安全,因此必须调整代码。
以下是一些限制:
1)errorList-此处不能为null,因此对.stream()
的调用是安全的-当它为空时,它只会返回false
2)getErrorSegment()
和getErrorDetails()
都可以为空,这就是为什么我使用类似的过滤器以确保它们都不为空的原因
3)getErrorCode()
可以为null,但是它永远不会抛出NPE,因为与null匹配时它只会返回false-我可以。
您将如何改善该流?我觉得自己的.filter()
不好,可以做得更好。最近写了很多这样的代码,因为我不确定该流如何处理空值,并且不想在.map()
中获得NPE,因为它被调用为空值
答案 0 :(得分:8)
您可以通过以下方式更优雅地过滤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()));
}
答案 1 :(得分:2)
我认为写此代码的最好方法是定义一个单独的方法,该方法使用Optional来避免空值。然后,您可以在流中使用方法引用来引用它:
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);
}
您的类名可能与方法引用不同。您的代码没有显示使用了什么类,所以我只是使用了合理的猜测。