Java 8 flatMap + Optional.of不编译

时间:2014-10-28 15:14:45

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

我试图在Java中flatMap Optional。这是一个简化的例子:

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以便编译?

2 个答案:

答案 0 :(得分:6)

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());

请注意,如果您的目标只是删除某些值(&#34; b&#34;在您的示例中),则根本不需要使用Optional。您只需过滤流:

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

这样您就不需要flatMap,而您的输出是List<String>而不是List<Optional<String>>

正如Holger所评论的那样,使用Stream代替Optional可以简化返回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());

答案 1 :(得分: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());