我正在尝试用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以便进行编译?
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。您只需过滤流:
List<String> result =
x.stream()
.filter (val -> !val.equals("b"))
.collect(Collectors.toList());
这样您就不需要flatMap
,并且您的输出是List<String>
而不是List<Optional<String>>
。
正如Holger所评论的,返回Optional
s的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());
这里不需要处理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());