如何使用null检查连续生成java 8 Stream映射

Dan*_*yen 9 java java-8 java-stream

我有这段代码

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")));
Run Code Online (Sandbox Code Playgroud)

这完全可以正常工作,但我认为它有点乱,并没有涵盖所有null pointer exception可能的(见评论).

我尝试将此代码重构为

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

在我将生命映射到覆盖范围后,它似乎不再是一个覆盖列表.所以问题是如何将第一部分重构为null安全并且可能缩短它?

Ous*_* D. 5

Life::getCoverages返回一个集合,因此过滤器Coverage::isMainplan将不起作用,相反,您应该flatMap返回之后的序列,.map(Life::getCoverages)然后对进行filter操作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(...);
Run Code Online (Sandbox Code Playgroud)

我在代码中添加了一些内容:

  1. 我添加了.filter(Objects::nonNull)之后.map(Life::getCoverages),您可以取消注释,因为返回的元素可能为null。
  2. 我添加了.flatMap(Collection::stream)一个返回的流,该流包含将流中的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容的结果。
  3. 我添加了另一个.filter(Objects::nonNull),您可以取消注释,因为返回的元素flatMap可能为空。
  4. 然后,我们处于可以应用的阶段,.filter(Coverage::isMainplan)最后,通过检索第一个符合条件的对象findFirst,如果不存在,则通过提供默认值orElse

我建议看看以下博客以熟悉该flatMap方法: