【问题标题】:How return null by using Stream API?如何使用 Stream API 返回 null?
【发布时间】:2018-07-27 13:36:57
【问题描述】:

所以,我有一个ArrayList 的自动生成字符串。我想找到包含某个字符的第一个元素,否则如果没有与此过滤器匹配的元素,则应用另一个过滤器。换一种方式,我想返回null对象。

所以我写了这个 lambda 表达式:

str.stream()
   .filter(s -> s.contains("q"))
   .findFirst()
   .orElseGet(() -> str.stream()
                       .filter(s -> s.contains("w"))
                       .findFirst()
                       .orElseGet(null))

但如果没有一个元素与这两个过滤器匹配,我将出现 NullPointerException。怎么样,我可以得到类似的东西:return null

【问题讨论】:

  • 不要。相反,返回一个Optional 并让客户决定如何处理它。
  • 但是想一想,您真的想返回那个null 以便进一步解决问题吗?可能是默认值?或者更好地早点抛出异常?
  • @Eugene 使用 FP 和 null... 这不是最好的选择,但如果必须,我宁愿先抛出异常而不是处理 null。

标签: java lambda java-8 java-stream optional


【解决方案1】:

除非我遗漏了一些明显的东西,否则只需 .orElse(null) 而不是最后一个 orElseGetorElseGet 接受 Supplier 并传递 null,在空引用上调用 get(),嗯...

【讨论】:

    【解决方案2】:

    另一种更简单的方法:您可以过滤包含qw的字符串,然后排序以首先移动包含q的字符串,先查找,如果可选为空则返回null:

    str.stream()
        .filter(s -> s.contains("q") || s.contains("w"))
        .sorted((s1, s2) -> s1.contains("q") ? -1 : 1 )
        .findFirst()
        .orElse(null);
    

    .sorted((s1, s2) -> s1.contains("q") ? -1 : 1 ) 将首先移动包含"q" 的字符串。由于仅对包含 qw 的值过滤了流,因此返回 null 只会发生,不会保留任何元素。

    【讨论】:

    • 我想过这个,太复杂了:(
    • @AndrewTobilko 我会支持这个,我想用这样的方式编辑我的答案,但是既然你发布了......
    • @AndrewTobilko 我更喜欢它,因为我确信只遍历流一次。它是大型流的更好选择。
    • @ernest_k,我支持迭代一次的想法(将其添加到我的答案中),但是,恕我直言,过滤会使事情复杂化
    • 赞成,绝对是一种更好的方法,因为无论内容是什么,遍历都是一次完成。
    【解决方案3】:

    问题是Optional::orElseGet(null) 接受Supplier<T> 并抛出NullPointerException

    使用Optional::orElse(null) 接受T,在您的情况下为String

    以下代码有效:

    List<String> str = Arrays.asList("a", "b", "c");
    String output = str.stream()
                       .filter(s -> s.contains("q"))
                       .findFirst()
                       .orElseGet(() -> str.stream()
                                           .filter(s -> s.contains("w"))
                                           .findFirst()
                                           .orElse(null));                 // <-- HERE
    
    System.out.println(output);    // Prints null
    

    或者,使用Optional::orElseGet(Supplier&lt;? extends T&gt; other) 返回nullSupplier 本身不能是null

    .orElseGet(() -> null));
    

    【讨论】:

      【解决方案4】:

      orElseGet 需要 Supplier,您需要传递一个值,orElse 就是这种情况。

      我不会在这里使用 Stream API,一次迭代就足以解决问题:

      String wString = null;
      for (String s : str) {
          if (s.contains("q")) return s;
          if (s.contains("w") && wString == null) wString = s;
      }
      return wString;
      

      【讨论】:

        猜你喜欢
        • 2017-08-13
        • 2021-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-15
        • 2021-10-28
        • 1970-01-01
        • 2015-11-27
        相关资源
        最近更新 更多