如何直接映射/扩展对象流?

时间:2015-02-10 16:14:18

标签: java dictionary tree java-8 reduce

是否可以直接将对象扩展为流?

我目前的做法是:

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扩展为Stream ?

我需要的是:

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))

但仍然想知道是否有更优雅的方式。

2 个答案:

答案 0 :(得分:2)

您始终可以使用OptionalStream转换为由{0}组成的optional.map(Stream::of).orElseGet(Stream::empty)。如果流的项目可以提供Stream,您实际上想要处理,您可以使用flatMap将流的项目替换为评估的结果流,或者如果{{1空的。

E.g。

Optional

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

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

答案 1 :(得分:1)

  

它运作得很好(是的,我知道它现在很丑陋)但是只是讨厌使用orElseGet和steam从Optional转换为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;
}

如果您认为情况更糟,另一种解决方法是在Node类中提供一个直接返回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);
}
  

是否可以直接将对象扩展为流?

是的,Stream.of用于此目的,但由于getBranch返回Set,因此您不需要它,因此您只需要调用stream()它来得到结果流。