当前位置: 首页 > 知识库问答 >
问题:

如何使用流平均大小数?

林建本
2023-03-14

我想采取以下方法:

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

并使用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);
}

有没有办法在不流式传输两次(第二次获得计数)的情况下做到这一点?

共有3个答案

范朗
2023-03-14

或者,您可以使用此Collector实现:

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

}

这样使用:

BigDecimal mean = bigDecimals.stream().collect(new BigDecimalAverageCollector());

注意:示例使用Project Lombok注释来缩短粘合代码。

秦伯寅
2023-03-14

你不需要流两次。只需调用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);
}
薛经艺
2023-03-14
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);

对于那些认为有帮助的人,代码的可选文本描述(如果您发现代码足够自解释,请忽略):

  • 将大小数列表转换为流
 类似资料:
  • 问题内容: 我试图显示最高平均工资;但是,我似乎无法使其正常工作。 我可以得到要显示的平均薪水清单: 但是,当我尝试显示具有以下项的最大平均薪水列表时: 它没有运行。我收到“无效标识符”错误。如何使用每个工人的平均工资来找到每个工人的最高平均工资? 谢谢。 问题答案: 由聚合函数(例如avg)产生的列通常获得任意名称。只需为其使用别名,然后在其上进行选择:

  • 我需要使用流创建两个方法。返回每个任务平均分数的方法。 以及一种返回平均得分最高的任务的方法。 我只能修改这两种方法。 这是CourseResult课程 以及创建CourseResult对象的方法。 基于这些方法,我可以通过将该任务的分数之和除以3来计算每个任务的平均值,因为只有3个人可以让它除以一个等于流中CourseResult对象数量的数字,如果这些方法改变了它们的. limited(3)。

  • 是否可以对流进行求和、平均并将其转换为新对象。我有个目标 现在我想得到这个对象列表的平均值和总和(代码总和价格和代码平均价格) 然后我想创建一个新对象(页脚 这就是我现在所拥有的,它可以工作,但是我要通过两次流。我想要一个方法,我可以通过一次流来做到这一点。 有没有更好的方法做到这一点而不必重复这一点。谢谢

  • 这是我的代码,它根据一个人所做测试的平均分数返回一个分数。 以下是CourseResult类供参考 和2种生成测试分数的方法。历史结果 和编程结果 所以每个人有3个测试分数。如果我使用编程生成分数,结果很好,因为只有3个编程测试,但是如果我使用历史生成分数,结果我也每个人得到3个测试分数,但是我应该把它当作第四个测试根本没有尝试,这意味着0分。我如何让我的定义标记方法得到收集的测试分数的平均值,而