首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >BigDecimal摘要统计信息

BigDecimal摘要统计信息
EN

Stack Overflow用户
提问于 2018-08-02 12:18:49
回答 3查看 2.3K关注 0票数 6

我有一份BigDecimals的名单。

代码语言:javascript
运行
复制
List<BigDecimal> amounts = new ArrayList<>()

如何使用Java8 streams获得上述列表的汇总统计数据,同时又不会损失BigDecimal小数位3-4位的精度?

EN

回答 3

Stack Overflow用户

发布于 2018-08-02 19:30:38

我创建了this answer的通用摘要统计信息收集器的BigDecimal专门化,允许对其进行扩展以支持求和,因此还可以计算平均值:

代码语言:javascript
运行
复制
/**
 * Like {@code DoubleSummaryStatistics}, {@code IntSummaryStatistics}, and
 * {@code LongSummaryStatistics}, but for {@link BigDecimal}.
 */
public class BigDecimalSummaryStatistics implements Consumer<BigDecimal> {

    public static Collector<BigDecimal,?,BigDecimalSummaryStatistics> statistics() {
        return Collector.of(BigDecimalSummaryStatistics::new,
            BigDecimalSummaryStatistics::accept, BigDecimalSummaryStatistics::merge);
    }
    private BigDecimal sum = BigDecimal.ZERO, min, max;
    private long count;

    public void accept(BigDecimal t) {
        if(count == 0) {
            Objects.requireNonNull(t);
            count = 1;
            sum = t;
            min = t;
            max = t;
        }
        else {
            sum = sum.add(t);
            if(min.compareTo(t) > 0) min = t;
            if(max.compareTo(t) < 0) max = t;
            count++;
        }
    }
    public BigDecimalSummaryStatistics merge(BigDecimalSummaryStatistics s) {
        if(s.count > 0) {
            if(count == 0) {
                count = s.count;
                sum = s.sum;
                min = s.min;
                max = s.max;
            }
            else {
                sum = sum.add(s.sum);
                if(min.compareTo(s.min) > 0) min = s.min;
                if(max.compareTo(s.max) < 0) max = s.max;
                count += s.count;
            }
        }
        return this;
    }

    public long getCount() {
        return count;
    }

    public BigDecimal getSum()
    {
      return sum;
    }

    public BigDecimal getAverage(MathContext mc)
    {
      return count < 2? sum: sum.divide(BigDecimal.valueOf(count), mc);
    }

    public BigDecimal getMin() {
        return min;
    }

    public BigDecimal getMax() {
        return max;
    }

    @Override
    public String toString() {
        return count == 0? "empty": (count+" elements between "+min+" and "+max+", sum="+sum);
    }
}

它可以使用类似于DoubleSummaryStatistics的对等物,例如

代码语言:javascript
运行
复制
BigDecimalSummaryStatistics bds = list.stream().collect(BigDecimalSummaryStatistics.statistics());

作为完整的示例:

代码语言:javascript
运行
复制
List<BigDecimal> list = Arrays.asList(BigDecimal.ZERO, BigDecimal.valueOf(-2), BigDecimal.ONE);
BigDecimalSummaryStatistics bds = list.stream().collect(BigDecimalSummaryStatistics.statistics());
System.out.println(bds);
System.out.println("average: "+bds.getAverage(MathContext.DECIMAL128));
代码语言:javascript
运行
复制
3 elements between -2 and 1, sum=-1
average: -0.3333333333333333333333333333333333
票数 14
EN

Stack Overflow用户

发布于 2019-06-26 07:35:21

您可以将Java Streams与具有BigDecimalSummaryStatistics类的Eclipse Collections一起使用:

代码语言:javascript
运行
复制
List<BigDecimal> amounts = 
        Lists.mutable.with(BigDecimal.ONE, BigDecimal.TEN, BigDecimal.ZERO, BigDecimal.ONE);

BigDecimalSummaryStatistics stats =
        amounts.stream().collect(Collectors2.summarizingBigDecimal(each -> each));

Assert.assertEquals(BigDecimal.ZERO, stats.getMin());
Assert.assertEquals(BigDecimal.TEN, stats.getMax());
Assert.assertEquals(BigDecimal.valueOf(12L), stats.getSum());
Assert.assertEquals(BigDecimal.valueOf(3L), stats.getAverage());
Assert.assertEquals(4L, stats.getCount());

注意:我是Eclipse Collections的提交者

票数 5
EN

Stack Overflow用户

发布于 2018-08-02 17:21:11

如果您愿意使用第三方库(与Java8Streams兼容),则可以使用jOOλ,您可以使用它来编写:

代码语言:javascript
运行
复制
Tuple5<
    Long, 
    Optional<BigDecimal>, 
    Optional<BigDecimal>, 
    Optional<BigDecimal>, 
    Optional<BigDecimal>
> tuple
amounts.stream()
       .collect(Tuple.collectors(
           Agg.sum(),
           Agg.count(),
           Agg.avg(),
           Agg.<BigDecimal>min(),
           Agg.<BigDecimal>max()
       ));

这不会导致精度损失,但可能比聚合双精度要慢得多。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51645432

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档