【问题标题】:how to filter elements that throw exception during stream map如何过滤在流映射期间抛出异常的元素
【发布时间】:2018-11-15 15:25:47
【问题描述】:

我正在关注文章https://www.oreilly.com/ideas/handling-checked-exceptions-in-java-streams 将方法提取到方法中,以处理异常,并注意到给出的示例看起来很干净,因为它们实际上没有编译,因为它们错过了返回语句。
本质上,我希望有一个类似于文章示例 3 中的“除法”的解析方法,但我的解析列表,在某些情况下,它会抛出错误,记录它们并继续,如下所示:

public List<String> validator(List<String> values) {
    return values.stream()
        .map(this::parse)
        .filter(Objects::nonNull)
        .collect(Collectors.toList());
}
public String parse(String s){
    try{
         // returns something or throws exceptions
    } catch (Exception e ){
       log(e)
    }
    return null;
}

正如您从这段代码中看到的那样,我通过在 parse 方法的末尾返回一个 null 来欺骗编译错误,然后我在收集之前在我的验证器上过滤 null,它看起来令人震惊。有没有更好的方法以简洁的方式跳过这些值?

【问题讨论】:

  • 如果parse在成功的情况下从不返回null,这是一个很好的解决方案。另一种方法是让parse 返回Optional&lt;String&gt;,但在Java 9 之前,流代码看起来不会比你已经拥有的更好。从 Java 9 开始,您可以使用 .flatMap(s -&gt; parse(s).stream())
  • 好点。但我会将您的.flatMap(s -&gt; parse(s).stream()) 分成两个步骤,例如.map(this::parse).flatMap(Optional::stream)。恕我直言,这更容易阅读。
  • 我实际上考虑使用 Optional 但做 .filter(Optional::isPresent).map(Optional::get) 只是读 .filter(Objects::nonNull) 的内容要多得多,但是是的它可能会导致将来有人重用我的方法并将空指针指向下巴。顺便说一句,oracle 不再支持 java 9 和 10,我认为可选的平面图优化将适用于 java 11,对吗?
  • 当然,它也适用于 Java 11。对于 Java 8,您可以创建一个辅助方法 public static &lt;T&gt; Stream&lt;T&gt; stream(Optional&lt;T&gt; o) { return o.map(Stream::of).orElseGet(Stream::empty); }。然后,您可以使用接近 Java 9+ 变体的解决方案,.flatMap(s -&gt; stream(parse(s)))

标签: java collections java-8 exception-handling java-stream


【解决方案1】:

对我来说,你跳过null 元素的方式非常好。

但是,如果您想以功能方式执行此操作,请完全避免返回 null。改为返回Optional

public Optional<String> parse(String s){
    try{
        return Optional.of(<parsed_value>);
    } catch (Exception e ){
        log(e);
    }
    return Optional.empty();
}

Java 1.8解决方案:

public List<String> validator(List<String> values) {
     return values.stream()
                  .map(this::parse)
                  .filter(Optional::isPresent)
                  .map(Optional::get)
                  .collect(Collectors.toList());
}

Java 1.9+ 解决方案:(由 @Holger 提出):

 public List<String> validator(List<String> values) {
     return values.stream()
                  .map(this::parse)
                  .flatMap(Optional::stream)
                  .collect(Collectors.toList());
}

【讨论】:

    猜你喜欢
    • 2018-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多