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

我有下面的代码,我试图改善:

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

它的工作,但它真的觉得有一个更好的办法做到这一点。 有人可以在这个问题上给我启发吗?

如果所有这些属性都是相同的types(它们看起来都是BigDecimal ),则可以使用flatMap创build它们的单个Stream ,然后reduce其全部reduce为:

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

您可以简单地链接地图内的所有属性:

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

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

如果您可以将以下方法添加到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); 

“更好”或“最好”这个词应该是指某种度量。 性能? 可读性? 优雅?

Eran的答案显示了一种方法,即为每个员工创build包含属性值A,B,C和D的小stream,并将这些值平面映射到更大的stream中。 这种方法的总结顺序是

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

另一个select是创build属性A,B,C和D的各个stream,并在应用还原之前连接这些stream。 这可以使用嵌套的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 

(在技术上可能不会有很大的差别,但是这是一种在概念上不同于迄今为止提出的方法(按求和顺序)的方法,因此可以作为一个选项值得一提 – 另外,它与您目前使用的方法更类似,但是没有用于减less的破坏的身份值)

或者只是一个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 }); 

作为一个方面 – 不是你目前的实施是错误的,因为你违反了减less的identity