提问者:小点点

Stream.anyMatch 中的异常


我有一些正在使用javaapi的代码:

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。

非常感谢。


共2个答案

匿名用户

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调用的输入。