【问题标题】:using a stream based on the content of Optional<Map>使用基于 Optional<Map> 内容的流
【发布时间】:2017-06-21 03:52:59
【问题描述】:

我从不受我控制的服务中获取了一个地图,该地图可能为 null,并且想要对其进行处理,比如过滤、映射和缩减为我需要的单个元素。

问题:是否有从 Optional 到 Stream 的“链接”?

我尝试过(除其他外):

 return Optional.ofNullable(getMap())
   .map(Map::entrySet) // gets the entryset
   .map(Stream::of)
   .orElseGet(Stream::empty)
   // i would then like to continue with
   .filter(e -> e.getKey().startsWith("f")
   .map(Entry::getValue)
   .findFirst();

但后来我得到的不是Stream&lt;Entry&gt;,而是Stream&lt;Set&lt;Entry&gt;&gt; ...有没有办法以某种方式将集合或映射出Optional?

注意:我对这里的流畅、纯流/可选方法感兴趣。当我首先将地图保存到本地 var 并确保它不为空时,它当然可以工作。

【问题讨论】:

  • 将 Stream 转换为 Stream?不,我不能。
  • 您可能应该考虑更改您的getMap() 以返回一个空地图而不是null。那时您不会将其包装在Optional 中,并且您可以轻松避免此类问题。正如Stuart Marks 所说,Rule #4: It's generally a bad idea to create an Optional for the specific purpose of chaining methods from it to get a value.
  • 在 Java 9 中,Optional will have a stream() method,您可以这样做:Optional.ofNullable(getMap()).map(Map::entrySet).stream().flatMap(Set::stream)...
  • 是的,这看起来很有希望……但是我在企业环境中,我们花了几年时间才采用 Java8……不确定我会在 7 月切换 :-(跨度>
  • @JanGalinski 如果你是在企业环境中,已经采用了java8,应该庆幸,我想……我不会采用Java9,直到它相当成熟并且框架和库都一样成熟。

标签: java java-stream


【解决方案1】:

你的错误在这一行:

.map(Stream::of)

of 函数采用单个参数(或可变参数),并返回仅包含该元素的流。因此,您将获得Stream&lt;Set&lt;Map.Entry&gt;&gt;。相反,您应该在入口集上调用流方法,如下所示:

.map(Set::stream)

【讨论】:

    【解决方案2】:

    我想我会回答这个问题。

     return Optional.ofNullable(getMap())
       .map(Map::entrySet) // gets the entryset
       .map(Stream::of)
       .orElseGet(Stream::empty)
       // i would then like to continue with
       .filter(e -> e.getKey().startsWith("f")
       .map(Entry::getValue)
       .findFirst();
    

    当我看到上面的代码时,我病了,真的病了。以流利的方式编写代码而不是编写简单的代码对您来说真的那么重要吗?首先,正如@Didier L 在cmets 中提到的那样,使用Optional 是错误的方式。其次,代码很难阅读,不是吗?如果你用定义一个局部变量来编写它:

    Map<String, Integer> map = getMap();
    
    return map == null ? Optional.<Integer> empty() 
                       : map.entrySet().stream()
                            .filter(e -> e.getKey().startsWith("f")).map(Entry::getValue).findFirst();
    

    不是很清楚吗?或者,如果您无法克服不使用流利的方法,您可以使用 StreamEx 来完成:

    StreamEx.ofNullable(getMap())
            .flatMapToEntry(Function.identity())
            .filterKeys(k -> k.startsWith("f")).values().findFirst();
    

    或者我的图书馆AbacusUtil

    EntryStream.of(getMap()).filterByKey(k -> k.startsWith("f")).values().first();
    

    如果遇到困难,总是试图寻找更好的方法。

    【讨论】:

      猜你喜欢
      • 2012-09-04
      • 1970-01-01
      • 2021-09-05
      • 2021-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-01
      • 2015-01-16
      相关资源
      最近更新 更多