【问题标题】:Java 8 flatMap + Optional.of doesn't compileJava 8 flatMap + Optional.of 无法编译
【发布时间】:2014-12-24 01:36:00
【问题描述】:

我正在尝试在 Java 中 flatMapOptionals。这是一个简化的例子:

List<String> x = Arrays.asList("a", "b", "c");
List<String> result = x.stream().flatMap((val) -> val.equals("b") ? Optional.empty() : Optional.of(val)).collect(Collectors.toList());

我从编译器收到此错误消息:

Error:(10, 27) java: incompatible types: no instance(s) of type variable(s) T exist so that java.util.Optional<T> conforms to java.util.stream.Stream<? extends R>

怎么了?这是我在 Scala 中尝试实现的示例:

List("a", "b", "c").flatMap(x => if (x == "b") None else Some(x))

返回:

res2: List[String] = List(a, c)

正如预期的那样。

如何将其转换为 Java 以便编译?

【问题讨论】:

    标签: java functional-programming java-8 optional flatmap


    【解决方案1】:

    flatMap 应将输入 Stream 的元素映射到不同的 Stream。因此它必须返回Stream 而不是Optional

    因此,你应该这样做:

    List<String> x = Arrays.asList("a", "b", "c");
    List<Optional<String>> result = 
        x.stream()
         .flatMap((val) -> 
                      val.equals("b") ? Stream.of(Optional.empty()) : 
                                        Stream.of(Optional.of(val)))
         .collect(Collectors.toList());
    

    请注意,如果您的目标只是去除某些值(示例中的“b”),则根本不需要使用 Optional。您可以只过滤 Stream :

    List<String> result = 
        x.stream()
         .filter (val -> !val.equals("b"))
         .collect(Collectors.toList());
    

    这样你就不需要flatMap,你的输出是List&lt;String&gt;而不是List&lt;Optional&lt;String&gt;&gt;

    正如 Holger 所评论的,返回 Optionals 的 Stream 的解决方案可以通过使用 map 而不是 flatMap 来简化,因为每个元素都映射到单个 Optional

    List<String> x = Arrays.asList("a", "b", "c");
    List<Optional<String>> result = 
        x.stream()
         .map((val) -> val.equals("b") ? Optional.empty() : Optional.of(val))
         .collect(Collectors.toList());
    

    【讨论】:

    • 谢谢!通常我会过滤。在这种情况下(真实情况,而不是简化的玩具示例),我宁愿使用 Optionals,因为过滤意味着要挖掘很多废话,我还必须在 map 阶段做这些。
    • 当流的每个元素都映射到一个Optional时,就没有必要使用flatMap了。只需使用.map(val -&gt; val.equals("b")? Optional.empty(): Optional.of(val))
    • @Holger 你是绝对正确的。我没有考虑。我遵循了 OP 使用 flatMap 的决定。
    • @Holger 如果我只使用 .map 而不是 .flatMap,我会得到 List> 而不是所需的 List。而且也没有像 scala 中那样的扁平化:( 那么到达 List 的最简单方法是什么?我知道我可以过滤然后再次映射,但它开始太冗长了......
    • 是的,我在第一条评论中说过为什么我想使用 Optional。在这个玩具示例中,是的过滤器将是要走的路。但我有一个真实的案例,可选的会更好(但似乎只有在 Scala 中,Java 似乎并没有削减它)
    【解决方案2】:

    这里不需要处理Optional

    最简单直接的解决方案是使用filter

    List<String> result = x.stream()
        .filter(val -> !val.equals("b"))
        .collect(Collectors.toList());
    

    如果你坚持使用flatMap,你应该简单地使用Stream而不是Optional

    List<String> result = x.stream().flatMap(
        val -> val.equals("b")? Stream.empty(): Stream.of(val))
        .collect(Collectors.toList());
    

    如果您必须处理不可避免地产生Optional 的操作,则必须将其转换为Stream 以使用Stream.flatMap

    List<String> result = x.stream()
        .map(val -> val.equals("b") ? Optional.<String>empty() : Optional.of(val))
        .flatMap(o->o.map(Stream::of).orElse(Stream.empty()))
        .collect(Collectors.toList());
    

    【讨论】:

      猜你喜欢
      • 2021-06-30
      • 1970-01-01
      • 2016-05-17
      • 1970-01-01
      • 2017-04-09
      • 1970-01-01
      • 2015-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多