可选流到可选流的Java可选流

可选流到可选流的Java可选流,java,functional-programming,Java,Functional Programming,我需要将流转换为可选 当流的至少一个值为空时,输出可选应为空值 你知道解决这个问题的有效方法吗?我试着使用收集方法,但没有成功。好吧,这里有一件棘手的事情,如果你只得到一个流,你只能使用一次 要保持无状态并避免重复复制,一种方法是只捕获NoTouchElementException: static <T> Optional<Stream<T>> invert(Stream<Optional<T>> stream) { try {

我需要将
转换为
可选

的至少一个值为空时,输出
可选
应为空值


你知道解决这个问题的有效方法吗?我试着使用
收集
方法,但没有成功。

好吧,这里有一件棘手的事情,如果你只得到一个
流,你只能使用一次

要保持无状态并避免重复复制,一种方法是只捕获NoTouchElementException

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();
    }
}
静态可选反转(流){
试一试{
返回可选的.of(
stream.map(可选::get)
.collect(收集器.toList())
.stream());
}捕获(无接触元素例外e){
返回可选的.empty();
}
}
一个简单的反转是:

static <T> Optional<Stream<T>> invert(Stream<Optional<T>> stream) {
    return Optional.of(stream.map(Optional::get));
}
静态可选反转(流){
返回Optional.of(stream.map(Optional::get));
}
但要确定它是否包含空元素,您需要实际遍历它,它也会使用它

如果给定了流的源,则可以在不收集流的情况下遍历流:

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));
}
静态可选反转(
供应商(供应商){
//利用此处的短路
//而不是allMatch(可选::isPresent)
返回supplier.get().anyMatch(o->!o.isPresent())?
Optional.empty():Optional.of(supplier.get().map(Optional::get));
}
列出myint=
asList(可选的(1),可选的(2),可选的(3));
可选反转=反转(myInts::stream);

这可能是一种更有趣的方法。(但是它很容易出现竞争条件,因为
stream()
被占用两次。如果其他线程在中间添加了一个空元素并将其带走,则会出现问题。)

类似于Radiodef的答案,尽管此选项避免了异常处理和中间列表

private static <T> Optional<Stream<T>> invertOptional(Stream<Optional<T>> input) {
    return input.map(integer -> integer.map(Stream::of))
            .collect(Collectors.reducing((l, r) -> l.flatMap(lv -> r.map(rv -> Stream.concat(lv, rv)))))
            .orElse(Optional.empty());
}
私有静态可选(流输入){
返回input.map(integer->integer.map(Stream::of))
.collect(收集器.还原((l,r)->l.flatMap(lv->r.map(rv->Stream.concat(lv,rv‘‘)’))
.orElse(可选.empty());
}
其工作方式是将其映射到T的可选流。本例中使用了
Optional.map
,因此结果流中的每个
Optional
项都是1的流或空可选项

然后通过将这些流减少到一起来收集这些流。如果l为空,
l.flatMap
将返回空可选值,或者
r.map
返回空值。如果r.map不是空的,它将调用Stream.concat,它组合了左流和右流的值

整个collect减少生成了一个
可选的
,因此我们使用
.orElse(Optional.empty)


注意:代码已经过测试,看起来正常工作。空输入流的未指定“边缘情况”被视为空可选,但可以很容易地更改。

虽然这一问题已经得到解答,但随着Java-9的引入,这应该可以通过以下方式实现:

// initialized stream of optional
Stream<Optional<Integer>> so = Stream.empty(); 

// mapped stream of T 
Stream<Integer> s = so.flatMap(Optional::stream);   

// constructing optional from the stream
Optional<Stream<Integer>> os = Optional.of(s); 
//已初始化可选的流
Stream so=Stream.empty();
//映射的T流
streams=so.flatMap(可选::Stream);
//从流中构造可选的
可选操作系统=可选操作系统的数量;
最终流流ofits=流of(可选的(1)、可选的(2)、可选的(3)、可选的(4)、可选的(5));
//false-可选的.empty()列表;true->可选的.of(整数)列表
final-Map-collect=streamofits.collect(Collectors.partitionby(可选::isPresent));
最终函数mapToStream=List->List.stream().filter(o->o.isPresent()).map(o->o.get());
可选结果=可选
.of(可选).of(collect.get(false)).filter(list->list.size()>0.orElse(collect.get(true)))
.filter(list->list.size()>0)
.filter(列表->列表.get(0).isPresent())
.map(mapToStream)
.map(可选::of)
.orElse(可选.empty());

我的回答也不是特别好,但这并不能解决前面提到的问题:如果任何
可选
为空,则
流应为空。这个答案只是过滤掉了空元素。
// initialized stream of optional
Stream<Optional<Integer>> so = Stream.empty(); 

// mapped stream of T 
Stream<Integer> s = so.flatMap(Optional::stream);   

// constructing optional from the stream
Optional<Stream<Integer>> os = Optional.of(s); 
    final Stream<Optional<Integer>> streamOfInts = Stream.of(Optional.of(1), Optional.of(2), Optional.of(3), Optional.of(4), Optional.of(5));

    // false - list of Optional.empty(); true -> list of Optional.of(Integer)
    final Map<Boolean, List<Optional<Integer>>> collect = streamOfInts.collect(Collectors.partitioningBy(Optional::isPresent));

    final Function<List<Optional<Integer>>, Stream<Integer>> mapToStream = List->List.stream().filter(o->o.isPresent()).map(o->o.get());

     Optional<Stream<Integer>> result = Optional
             .of(Optional.of(collect.get(false)).filter(list->list.size()>0).orElse(collect.get(true)))
             .filter(list->list.size()>0)
             .filter(list->list.get(0).isPresent())
             .map(mapToStream)
             .map(Optional::of)
             .orElse(Optional.empty());