使用Java 8减少链接的最佳方式

时间:2017-07-05 12:01:34

标签: java java-8

我有以下代码,我试图改进:

BigDecimal total = entity.getAssociate().stream().map(Associates::getPropertyA)
    .reduce(BigDecimal.ZERO, BigDecimal::add);
total = entity.getAssociate().stream().map(Associates::getPropertyB)
    .reduce(total, BigDecimal::add);
total = entity.getAssociate().stream().map(Associates::getPropertyC)
    .reduce(total, BigDecimal::add);
total = entity.getAssociate().stream().map(Associates::getPropertyD)
    .reduce(total, BigDecimal::add);

它有效,但真的感觉有更好的方法。有人可以就此事启发我吗?

5 个答案:

答案 0 :(得分:59)

如果所有这些属性属于同一类型(似乎它们都是BigDecimal),您可以使用flatMap创建所有属性Stream,然后{{1它总和:

reduce

答案 1 :(得分:32)

您可以直接在地图中添加所有属性:

BigDecimal total = entity.getAssociate().stream()
            .map(a -> a.getPropertyA()
                    .add(a.getPropertyB())
                    .add(a.getPropertyC())
                    .add(a.getPropertyD()))
            .reduce(BigDecimal.ZERO, BigDecimal::add);

请注意,这会改变添加数字的顺序。

答案 2 :(得分:23)

如果您可以将以下方法添加到Associates类:

public BigDecimal getSubtotal() {
    return propertyA.add(propertyB).add(propertyC).add(propertyD);
}

然后,完成任务很容易:

BigDecimal total = entity.getAssociate().stream()
    .map(Associate::getSubtotal)
    .reduce(BigDecimal::add)
    .orElse(BigDecimal.ZERO);

答案 3 :(得分:16)

“更好”或“最佳”这两个词应该指某个指标。性能?可读性?优雅?

answer by Eran显示了一种方法,即为每个关联创建包含属性值A,B,C和D的小流,并将这些值平面映射到更大的流中。这种方法的求和顺序是

A0 + B0 + C0 + D0  +  A1 + B1 + C1 + D1  + ... +  An + Bn + Cn + Dn

另一种选择是创建属性A,B,C和D的各个流,并在应用缩减之前连接这些流。这可以通过嵌套的Stream#concat调用完成,但使用带有标识函数的flatMap更优雅灵活:

Stream<BigDecimal> stream = Stream.of(
    entity.getAssociate().stream().map(Associates::getPropertyA),
    entity.getAssociate().stream().map(Associates::getPropertyB),
    entity.getAssociate().stream().map(Associates::getPropertyA),
    entity.getAssociate().stream().map(Associates::getPropertyC))
    .flatMap(Function.identity());

BigDecimal total = stream.reduce(BigDecimal.ZERO, BigDecimal::add);

关键是在这种情况下,求和顺序是

A0 + A1 + ... + An + B0 + B1 + ... + Bn + C0 + C1 + ... + Cn 

(技术上可能不会产生很大的差异。但是这是一种概念概念与目前已提出的方法(就总和顺序而言)不同的方法,因此,可能值得一提的是一个选项 - 另外,它更类似于您当前使用的方法,但没有用于减少的破坏的标识值)

答案 4 :(得分:6)

或只是forEach

BigDecimal[] total = new BigDecimal[] { BigDecimal.ZERO };
entity.getAssociate().stream().forEach(a -> {
    total[0] = total[0].add(a.getPropertyA());
    // ... and so on for all others
});

作为一个方面 - 由于您违反了identity减少量,因此当前的实施不是错误的。