用Java8中用Stream API对多个字段同时计算平均值

1.使用场景

比如评论系统中,我们有多项打分,我们要同时对多个评分项求平均值,这个在数据库可以直接通过SQL也可以解决,在java 8后提供的Stream API也能解决这种求值问题,不适合数据量太大的统计。

2.数据对象

/**
 * 用户评分实体
 */
public class UserCommentDTO implements Serializable {
    /**
     * 详细评价1(如:服务)
     */
    private Integer detailScore1;

    /**
     * 详细评价2(如:体验)
     */
    private Integer detailScore2;

    /**
     * 详细评价3(如:便捷)
     */
    private Integer detailScore3;

    /**
     * 详细评价4(如:性价比)
     */
    private Integer detailScore4;

}
/**
 * 计算实体
 */
public class CommentScoreVO implements Serializable {
    /**
     * 合计1
     */
    private Integer sum1 = 0;

    /**
     * 平均数1
     */
    private BigDecimal avg1;

    /**
     * 总数
     */
    private Integer count1 = 0;

    /**
     * 合计2
     */
    private Integer sum2 = 0;

    /**
     * 平均数2
     */
    private BigDecimal avg2;
    /**
     * 总数2
     */
    private Integer count2 = 0;

    /**
     * 合计3
     */
    private Integer sum3 = 0;

    /**
     * 平均数3
     */
    private BigDecimal avg3;
    /**
     * 总数3
     */
    private Integer count3 = 0;

    /**
     * 合计4
     */
    private Integer sum4 = 0;

    /**
     * 平均数4
     */
    private BigDecimal avg4;

    /**
     * 总数4
     */
    private Integer count4 = 0;

    public CommentScoreVO(UserCommentDTO userCommentDTO) {
        this.sum1 = userCommentDTO.getDetailScore1() == null ? 0 : userCommentDTO.getDetailScore1();
        this.sum2 = userCommentDTO.getDetailScore2() == null ? 0 : userCommentDTO.getDetailScore2();
        this.sum3 = userCommentDTO.getDetailScore3() == null ? 0 : userCommentDTO.getDetailScore3();
        this.sum4 = userCommentDTO.getDetailScore4() == null ? 0 : userCommentDTO.getDetailScore4();
        this.count1 = userCommentDTO.getDetailScore1() == null ? 0 : 1;
        this.count2 = userCommentDTO.getDetailScore2() == null ? 0 : 1;
        this.count3 = userCommentDTO.getDetailScore3() == null ? 0 : 1;
        this.count4 = userCommentDTO.getDetailScore4() == null ? 0 : 1;
    }

    public CommentScoreVO() {
    }

    public CommentScoreVO add(CommentScoreVO commentScoreVO) {
        this.sum1 += commentScoreVO.getSum1();
        this.sum2 += commentScoreVO.getSum2();
        this.sum3 += commentScoreVO.getSum3();
        this.sum4 += commentScoreVO.getSum4();
        this.count1 += commentScoreVO.getCount1();
        this.count2 += commentScoreVO.getCount2();
        this.count3 += commentScoreVO.getCount3();
        this.count4 += commentScoreVO.getCount4();
        return this;
    }

    public BigDecimal getAvg1() {
        return new BigDecimal(sum1).divide(new BigDecimal(count1), 1, RoundingMode.HALF_UP);
    }

    public BigDecimal getAvg2() {
        return new BigDecimal(sum2).divide(new BigDecimal(count2), 1, RoundingMode.HALF_UP);
    }

    public BigDecimal getAvg3() {
        return new BigDecimal(sum3).divide(new BigDecimal(count3), 1, RoundingMode.HALF_UP);
    }

    public BigDecimal getAvg4() {
        return new BigDecimal(sum4).divide(new BigDecimal(count4), 1, RoundingMode.HALF_UP);
    }

    public BigDecimal getEntireAvg() {
        return new BigDecimal(this.sum1 + this.sum2 + this.sum3 + this.sum4)
                .divide(new BigDecimal(this.count1 + this.count2 + this.count3 + this.count4), 1, RoundingMode.HALF_UP);
    }
}

3.代码实现

CommentScoreVO commentScore = userComments.stream().map(CommentScoreVO::new)
                    .reduce(new CommentScoreVO(), CommentScoreVO::add);

就是这么不可思议,用Stream API可以写出相当多的简洁代码。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值