Pat*_*ner 22 java collections bigdecimal java-8 java-stream
我想采取以下方法:
public BigDecimal mean(List<BigDecimal> bigDecimals, RoundingMode roundingMode) {
BigDecimal sum = BigDecimal.ZERO;
int count=0;
for(BigDecimal bigDecimal : bigDecimals) {
if(null != bigDecimal) {
sum = sum.add(bigDecimal);
count++;
}
}
return sum.divide(new BigDecimal(count), roundingMode);
}
Run Code Online (Sandbox Code Playgroud)
并使用Streams api更新它.这是我到目前为止所得到的:
public BigDecimal average(List<BigDecimal> bigDecimals, RoundingMode roundingMode) {
BigDecimal sum = bigDecimals.stream()
.map(Objects::requireNonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
long count = bigDecimals.stream().filter(Objects::nonNull).count();
return sum.divide(new BigDecimal(count), roundingMode);
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在没有两次流式传输的情况下做到这一点(第二次获得计数)?
Wil*_*ord 18
BigDecimal[] totalWithCount
= bigDecimals.stream()
.filter(bd -> bd != null)
.map(bd -> new BigDecimal[]{bd, BigDecimal.ONE})
.reduce((a, b) -> new BigDecimal[]{a[0].add(b[0]), a[1].add(BigDecimal.ONE)})
.get();
BigDecimal mean = totalWithCount[0].divide(totalWithCount[1], roundingMode);
Run Code Online (Sandbox Code Playgroud)
找到有用的代码的可选文本描述(如果您发现代码足够自我解释,请忽略).
a,(a,b)value具有第一个元素中的部分和和第二个元素中的部分计数.元素的第一个b元素包含要添加到总和的每个BigDecimal值.b没有使用第二个元素.xeh*_*puk 13
您不需要流两次.只需要List.size()点数:
public BigDecimal average(List<BigDecimal> bigDecimals, RoundingMode roundingMode) {
BigDecimal sum = bigDecimals.stream()
.map(Objects::requireNonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
return sum.divide(new BigDecimal(bigDecimals.size()), roundingMode);
}
Run Code Online (Sandbox Code Playgroud)
我使用上述方法来获取 BigDecimal 对象列表的平均值。该列表允许空值。
public BigDecimal bigDecimalAverage(List<BigDecimal> bigDecimalList, RoundingMode roundingMode) {
// Filter the list removing null values
List<BigDecimal> bigDecimals = bigDecimalList.stream().filter(Objects::nonNull).collect(Collectors.toList());
// Special cases
if (bigDecimals.isEmpty())
return null;
if (bigDecimals.size() == 1)
return bigDecimals.get(0);
// Return the average of the BigDecimals in the list
return bigDecimals.stream().reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal(bigDecimals.size()), roundingMode);
}
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用此收集器实现:
class BigDecimalAverageCollector implements Collector<BigDecimal, BigDecimalAccumulator, BigDecimal> {
@Override
public Supplier<BigDecimalAccumulator> supplier() {
return BigDecimalAccumulator::new;
}
@Override
public BiConsumer<BigDecimalAccumulator, BigDecimal> accumulator() {
return BigDecimalAccumulator::add;
}
@Override
public BinaryOperator<BigDecimalAccumulator> combiner() {
return BigDecimalAccumulator::combine;
}
@Override
public Function<BigDecimalAccumulator, BigDecimal> finisher() {
return BigDecimalAccumulator::getAverage;
}
@Override
public Set<Characteristics> characteristics() {
return Collections.emptySet();
}
@NoArgsConstructor
@AllArgsConstructor
static class BigDecimalAccumulator {
@Getter private BigDecimal sum = BigDecimal.ZERO;
@Getter private BigDecimal count = BigDecimal.ZERO;
BigDecimal getAverage() {
return BigDecimal.ZERO.compareTo(count) == 0 ?
BigDecimal.ZERO :
sum.divide(count, 2, BigDecimal.ROUND_HALF_UP);
}
BigDecimalAccumulator combine(BigDecimalAccumulator another) {
return new BigDecimalAccumulator(
sum.add(another.getSum()),
count.add(another.getCount())
);
}
void add(BigDecimal successRate) {
count = count.add(BigDecimal.ONE);
sum = sum.add(successRate);
}
}
}
Run Code Online (Sandbox Code Playgroud)
并使用它:
BigDecimal mean = bigDecimals.stream().collect(new BigDecimalAverageCollector());
Run Code Online (Sandbox Code Playgroud)
注意:示例使用Project Lombok注释来缩短粘合代码.
| 归档时间: |
|
| 查看次数: |
11009 次 |
| 最近记录: |