如何直接map/expand object to stream?

How to directly map/expand object to stream?

是否可以将一个对象直接扩展成一个流?

我目前的做法是:

private BigDecimal getNodeScore(Optional<Node> node) {
    return node.map(Node::getBranches)
               .orElseGet(Collections::emptySet)
               .stream()
               .filter(Branch::isValid)
               .flatMap(Branch::getLeafs)
               .map(Leaf::getScore)
               .reduce(BigDecimal::ZERO, BigDecimal::add);
}

它工作得很好(是的,我知道它很丑..现在)但只是讨厌使用 orElseGet 和 steam 从 Optional 过渡到 Stream 所以我想知道是否有任何方法可以将 Optional 扩展到流?

我需要的是:

private BigDecimal getNodeScore(Optional<Node> node) {
    return node.mapToStream(Node::getBranches)  // <-- Want something similar
               .filter(Branch::isValid)
               .flatMap(Branch::getLeafs)
               .map(Leaf::getScore)
               .reduce(BigDecimal::ZERO, BigDecimal::add);
}

我知道我总是可以创建一个辅助函数并用类似的东西包装第一个调用:

optionalToStream(node.map(Node::getBranches))

但是一直在想有没有更优雅的方式

It works quite well (yes, I know it's ugly.. for now) but is just hate using the orElseGet and steam to transition from Optional to Stream

老实说,我不觉得你的做法丑陋。您仍然可以使用 isPresent() 来测试可选值是否包含值。

private BigDecimal getNodeScore(Optional<Node> node) {
    return node.isPresent() ? node.get()
                                  .getBranch()
                                  .stream()
                                  .filter(Branch::isValid)
                                  .flatMap(Branch::getLeafs)
                                  .map(Leaf::getScore)
                                  .reduce(BigDecimal.ZERO, BigDecimal::add) : BigDecimal.ZERO;
}

如果您认为情况更糟,另一种解决方法是在您的节点 class 中提供一种方法,即 returns 直接 Stream<Branch>

private BigDecimal getNodeScore(Optional<Node> node) {
    return node.map(Node::getBranchesStream)
               .orElseGet(Stream::empty)
               .filter(Branch::isValid)
               .flatMap(Branch::getLeafs)
               .map(Leaf::getScore)
               .reduce(BigDecimal.ZERO, BigDecimal::add);
}

Is it possible directly expand an object into a stream?

是的,有 Stream.of 用于此目的,但您不需要它,因为 getBranch returns a Set,所以您只需调用stream() 获取结果流。

您始终可以使用 optional.map(Stream::of).orElseGet(Stream::empty)Optional 转换为由零个或一个元素组成的 Stream。如果流的项目可以提供 Stream,你确实想要处理,你可以使用 flatMap 将流的项目替换为评估的结果流,或者如果 [=13] 则保持空流=] 是空的。

例如

Optional<Node> optional=Optional.empty();
optional.map(Stream::of).orElseGet(Stream::empty)
   .map(Node::getBranches).flatMap(Collection::stream)
// follow-up operations

optional.map(Stream::of).orElse(Stream.empty())
   .flatMap(node -> node.getBranches().stream())
// follow-up operations

但在这种特殊情况下,您也可以将其融合为一个操作

optional.map(node -> node.getBranches().stream()).orElse(Stream.empty())
// follow-up operations

(但我认为在优化之前了解一般模式是值得的...)