You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Stream分组计算平均年龄后如何格式化Double保留两位小数

问题描述

我通过Java Stream分组得到了一个Map<String,Double>,该操作将球员按球队分组并计算每组的平均年龄,实现代码如下:

Map<String,Double> result = players.stream().collect(Collectors.groupingBy(Player::getTeam, Collectors.averagingInt(Player::getAge)));

打印结果时,输出的平均年龄小数位数过多,示例如下:

Tottenham Hotspur=25.333333333333332
Liverpool=26.333333333333332
Manchester City=23.666666666666668
Arsenal=24.0
Chelsea=25.333333333333332
Manchester United=23.0

我希望将小数部分限制为两位。已知两种实现两位小数的方法:

double value   = 12.34567;
double rounded = (double) Math.round(value * 100) / 100;

或转为字符串:

String result = String.format("%.2f", value);

但不知如何将这些方法结合到Stream收集过程中,请问是否有办法让结果Map中的值保留两位小数?

解决方案

有两种可行方案,分别对应你提到的两种处理方式:

1. 保留Map<String, Double>类型,对数值四舍五入

利用Collectors.collectingAndThen()包装平均值收集器,在得到原始平均值后立即做四舍五入处理:

Map<String, Double> result = players.stream()
    .collect(Collectors.groupingBy(
        Player::getTeam,
        Collectors.collectingAndThen(
            Collectors.averagingInt(Player::getAge),
            average -> (double) Math.round(average * 100) / 100
        )
    ));

此方式会将原始的多位小数Double值四舍五入为保留两位小数的结果,例如25.333333333333332会变为25.33,23.666666666666668变为23.67。

2. 转为Map<String, String>存储格式化后的字符串

如果仅用于展示,无需后续数值计算,可直接在收集时将平均值格式化为两位小数的字符串:

Map<String, String> result = players.stream()
    .collect(Collectors.groupingBy(
        Player::getTeam,
        Collectors.collectingAndThen(
            Collectors.averagingInt(Player::getAge),
            average -> String.format("%.2f", average)
        )
    ));

这种方式得到的Map值直接是符合格式要求的字符串,比如"25.33"、"24.00",打印时无需额外处理。

补充说明

  • 由于Double的精度特性,第一种方案中部分值可能仍存在微小的精度偏差(如25.33实际存储为25.330000000000001),若需精确计算,建议使用BigDecimal替代Double;
  • 第二种方案更适合仅用于展示的场景,彻底避免了浮点精度问题。

内容的提问来源于stack exchange,提问作者rosojit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 08:40:55