Nie*_*Nic 3 java functional-programming
我需要转换Stream<Optional<Integer>>为Optional<Stream<Integer>>.
Optional<Stream<Integer>>当至少有一个值为空时,输出应为空值Stream<Optional<Integer>>。
您知道解决问题的任何功能方法吗?我尝试使用collect方法,但没有成功。
好吧,这里的棘手之处在于,如果您只获得了一个Stream,则您只能使用它一次。
要无状态并避免冗余复制,一种方法是捕获NoSuchElementException:
static <T> Optional<Stream<T>> invert(Stream<Optional<T>> stream) {
try {
return Optional.of(
stream.map(Optional::get)
.collect(Collectors.toList())
.stream());
} catch (NoSuchElementException e) {
return Optional.empty();
}
}
Run Code Online (Sandbox Code Playgroud)
一个简单的反转是:
static <T> Optional<Stream<T>> invert(Stream<Optional<T>> stream) {
return Optional.of(stream.map(Optional::get));
}
Run Code Online (Sandbox Code Playgroud)
但是要确定它是否包含一个空元素,您需要实际遍历它并消耗它。
如果您获得了流的来源,则可以在不收集的情况下遍历它:
static <T> Optional<Stream<T>> invert(
Supplier<Stream<Optional<T>>> supplier) {
// taking advantage of short-circuiting here
// instead of allMatch(Optional::isPresent)
return supplier.get().anyMatch(o -> !o.isPresent()) ?
Optional.empty() : Optional.of(supplier.get().map(Optional::get));
}
Run Code Online (Sandbox Code Playgroud)
List<Optional<Integer>> myInts =
Arrays.asList(Optional.of(1), Optional.of(2), Optional.of(3));
Optional<Stream<Integer>> inverted = invert(myInts::stream);
Run Code Online (Sandbox Code Playgroud)
这可能是一种更有趣的方法。(但它很容易出现竞争条件,因为stream()取了两次。如果其他线程在两者之间添加了一个空元素并逃脱了它,我们就会遇到问题。)