添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have some code that is playing with the java stream 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));

And I sometime get an Exception pointing to the anyMatch line:

java.lang.NullPointerException: null at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:273) ~[na:na] at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na] at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na] at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1602) ~[na:na] at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129) ~[na:na] at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527) ~[na:na] at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513) ~[na:na] at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na] at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230) ~[na:na] at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196) ~[na:na] at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na] at java.base/java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:632) ~[na:na] at com.mycompany.routefilter.functionality.FunctionalityService.isAuthorizedRoute(FunctionalityService.java:55) ~[classes!/:1.0-SNAPSHOT] at

My question here is what is null ? Is it routeDefinition ? And why does it make the call fails ? I expect that if routeDefinition is null my method isMatchingRoute would return false.

Thank you.

we have no idea about any of the involved methods or data - how are we expected to know what is null - it could be .get(component) returning null (my favorite), or returning some collection with null elements; or auth.getTenantName(), routePath, isMatchingRoute, ... – user16320675 Jun 29, 2022 at 12:54

The NullPointerException is occurring in your .flatMap(Collection::stream) expression.

I created a similar example and expanded the method reference into a lambda. When causing a null value there you will see the stacktrace become more clear.

Example:

Stream.of("foo")
    .map(foo -> (List<String>) null)
    .flatMap(Collection::stream)
    .anyMatch(string -> "gnarly".equals(string)); // LINE 13

Leads to

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)

When I replace it with:

  Stream.of("foo")
        .map(foo -> (List<String>) null)
        .flatMap(strings -> strings.stream()) // LINE 11
        .anyMatch(string -> "gnarly".equals(string)); // LINE 12

Then the exception becomes:

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)

Here you see at the top of the stack trace that the real cause is in line 11. A bit confusing indeed, but I guess the JRE cannot report exceptions occurring within method references with line number accuracy.

EDIT: Regarding solutions, my IntelliJ suggests the following:

The filter:

.filter(Objects::nonNull)
.flatMap(Collection::stream)

The null safe lambda:

.flatMap(strings -> strings != null ? strings.stream() : null)

Your code is mainly failing at .flatMap(Collection::stream).

This is mostly because you are not handling null check in .map(auth -> auth.getAuthorizedRoutes().get(component)). So to avoid this scenario, you can either do filter before calling flatmap:

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

The hint which I have found out is based on java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230) ~[na:na] at line of stacktrace.

MatchOps$MatchOp is accepting predicate and determines if elements of source stream (in your case stream generated from flatMap) matches predicate or not. So this confirms that your flatMap is generating null value which in turn takes input of your map call.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.