我有一些正在使用java流
api的代码:
boolean isAuthorized = authorizationByTenant.stream()
.filter(auth -> auth.getTenantName().equalsIgnoreCase(tenant))
.map(auth -> auth.getAuthorizedRoutes().get(component))
.flatMap(Collection::stream)
.anyMatch(routeDefinition -> isMatchingRoute(routePath, routeDefinition));
我有时会收到一个指向anyMatch
行的异常
:
Java . lang . nullpointerexception:Java . base/Java . util . stream . reference pipeline $ 7 $ 1 . accept(reference pipeline . Java:273)~[na:na]at Java . base/Java . util . stream . reference pipeline $ 3 $ 1 . accept(reference pipeline . Java:197)~[na:na]at Java . base/Java . util . stream . reference pipeline $ 2 $ 1 . accept(reference pipeline . Java:179)~/:1.0-快照]在
我的问题是什么是<code>null</code>?是路由定义
吗?为什么它会使呼叫失败?我希望如果routeDefinition
为空,我的方法isMatchingRoute
将返回false。
非常感谢。
NullPointerException 发生在您的 .flatMap(Collection::stream)
表达式中。
我创建了一个类似的例子,并将方法引用扩展成一个lambda。当产生一个空值时,你会看到堆栈跟踪变得更加清晰。
例:
Stream.of("foo")
.map(foo -> (List<String>) null)
.flatMap(Collection::stream)
.anyMatch(string -> "gnarly".equals(string)); // LINE 13
导致
Exception in thread "main" java.lang.NullPointerException
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:271)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.Streams$StreamBuilderImpl.tryAdvance(Streams.java:397)
at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230)
at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:528)
at Test.main(Test.java:13)
当我将其替换为:
Stream.of("foo")
.map(foo -> (List<String>) null)
.flatMap(strings -> strings.stream()) // LINE 11
.anyMatch(string -> "gnarly".equals(string)); // LINE 12
那么例外就变成了:
Exception in thread "main" java.lang.NullPointerException
at Test.lambda$main$1(Test.java:11)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:271)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.Streams$StreamBuilderImpl.tryAdvance(Streams.java:397)
at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230)
at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:528)
at Test.main(Test.java:12)
在堆栈跟踪的顶部,您可以看到真正的原因在第11行。确实有点令人困惑,但是我猜JRE不能用行号的准确性来报告方法引用中发生的异常。
编辑:关于解决方案,我的IntelliJ建议如下:
过滤器:
.filter(Objects::nonNull)
.flatMap(Collection::stream)
空安全lambda:
.flatMap(strings -> strings != null ? strings.stream() : null)
你的代码主要在.flatMap(Collection::stream)
失败。
这主要是因为您没有在 .map(auth -
boolean isAuthorized = authorizationByTenant.stream()
.filter(auth -> auth.getTenantName().equalsIgnoreCase(tenant))
.map(auth -> auth.getAuthorizedRoutes().get(component))
.filter(auth -> auth.getAuthorizedRoutes().get(component)!= null)
.flatMap(Collection::stream)
.anyMatch(routeDefinition -> isMatchingRoute(routePath, routeDefinition));
我发现的提示是基于堆栈跟踪的行上的java.base/java.util.stream.MatchOps$MatchOps.validateSequential(MatchOps.java:230)~[na:na]。
< code > match ops$match op 接受谓词,并确定源流(在您的情况下,从< code>flatMap生成的流)的元素是否与谓词匹配。因此,这证实了您的平面图正在生成< code>null值,该值反过来接受您的< code>map调用的输入。