使用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
。