6

我正在尝试使用flatMap OptionalJava。这是一个简化的示例:

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

4

2 回答 2

6

flatMap预计将输入的元素映射Stream到不同的Stream. 因此它必须返回 aStream而不是 a 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了,你的输出是 aList<String>而不是 a List<Optional<String>>

正如 Holger 评论的那样,返回 a Streamof Optionals 的解决方案可以通过使用来简化,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());
于 2014-10-28T15:21:01.733 回答
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());

如果您必须处理不可避免地产生 a 的操作,Optional则必须将其转换为 a Streamfor using 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());
于 2014-10-28T17:10:27.727 回答