How to make java 8 Stream map continuously with null check

  • A+

I have this piece of code

Coverage mainCoverage = illus.getLifes().stream()     .filter(Life::isIsmain)     .findFirst()     .orElseThrow(() -> new ServiceInvalidAgurmentGeneraliException(env.getProperty("MSG_002")))     .getCoverages()       .stream() // <==may cause null here if list coverage is null     .filter(Coverage::isMainplan)     .findFirst()     .orElseThrow(() -> new ServiceInvalidAgurmentGeneraliException(env.getProperty("MSG_002"))); 

which is totally work fine but I think It's a little bit messy and not cover all the null pointer exception possible (see the comment).

I try to refactor this code into

Coverage mainCoverage1 = illus.getLifes().stream()     .filter(Life::isIsmain)     .map(Life::getCoverages)     .filter(Coverage::isMainplan) //<== cannot filter from list coverage to one main coverage     ... 

Seem after I map the life to coverage it is not a list of coverage anymore. So the question is how I can refactor the first section into null safe and maybe shorten it?


Life::getCoverages returns a collection hence the filter Coverage::isMainplan will not work, instead you should flatMap the sequences returned after .map(Life::getCoverages) then apply the filter operation on the Coverage:

Coverage mainCoverage =            illus.getLifes()                .stream()                .filter(Life::isIsmain)                               .map(Life::getCoverages)                //.filter(Objects::nonNull) uncomment if there can be null lists                .flatMap(Collection::stream) // <--- collapse the nested sequences                //.filter(Objects::nonNull) // uncomment if there can be null Coverage                .filter(Coverage::isMainplan)                .findFirst().orElse(...); 

I've added a few things to your code:

  1. I've added .filter(Objects::nonNull) after .map(Life::getCoverages) which you can uncomment given the elements returned could potentially be null.
  2. I've added .flatMap(Collection::stream) which returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element.
  3. I've added another .filter(Objects::nonNull) which you can uncomment given the elements returned after flatMap could potentially be null.
  4. We're then at a stage in which we can apply .filter(Coverage::isMainplan) and finally, retrieve the first object meeting the criteria via findFirst and if none then provide a default value via orElse.

I'd suggest having a look at the following blogs to get familiar with the flatMap method:


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: