Java 8 如何聚合重复键Map的值?解决IllegalStateException报错
Java 8 重复键Map数值聚合实现方案
异常根因
你之前遇到的IllegalStateException: Duplicate key异常,原因是使用的双参数版本Collectors.toMap()默认不支持重复键,一旦流处理过程中出现相同的键,就会直接抛出异常终止处理。这个方法要支持重复键场景,必须传入第三个参数——重复键的合并处理逻辑。
此外原代码末尾直接返回输入数组第一个元素的逻辑,没有使用聚合后的处理结果,也是需要修正的bug。
完整实现步骤
按照需求拆解,整个处理流程分为四步:
- 重复键聚合:给
toMap添加合并逻辑,碰到相同键时把对应的数值累加,替代默认的抛异常行为 - 无效值过滤:聚合完成后,移除所有求和结果为0的键值对
- 结果排序:对剩余的键值对,按键的字母自然升序排列
- 格式拼接:把排序后的条目拼成
key:value格式,用逗号连接成最终字符串
可运行代码
import java.util.Arrays; import java.util.Map; import java.util.stream.Collectors; public class MapAggregator { public static String Output(String[] strArr) { Map<String, Double> aggregatedResult = Arrays.stream(strArr) // 拆分每个"键:值"格式的字符串 .map(item -> item.split(":")) // 聚合相同键的数值,传入合并函数避免重复键异常 .collect(Collectors.toMap( splitPart -> splitPart[0], splitPart -> Double.parseDouble(splitPart[1]), (oldValue, newValue) -> oldValue + newValue )); // 过滤零值、排序、拼接最终输出 return aggregatedResult.entrySet().stream() // 排除求和后值为0的键 .filter(entry -> entry.getValue() != 0) // 按键字母升序排序 .sorted(Map.Entry.comparingByKey()) // 处理值的格式,避免出现整数转Double后带.0的问题,匹配示例输出 .map(entry -> { String key = entry.getKey(); Double value = entry.getValue(); String valueStr = value == value.longValue() ? String.valueOf(value.longValue()) : String.valueOf(value); return key + ":" + valueStr; }) // 用逗号拼接所有条目 .collect(Collectors.joining(",")); } // 对应需求的测试用例 public static void main(String[] args) { // 示例1:输入["B:-1", "A:1", "B:3", "A:5"] System.out.println(Output(new String[]{"B:-1", "A:1", "B:3", "A:5"})); // 输出A:6,B:2 // 测试用例2:输入{"X:-1", "Y:1", "X:-4", "B:3", "X:5"} System.out.println(Output(new String[]{"X:-1", "Y:1", "X:-4", "B:3", "X:5"})); // 输出B:3,Y:1 // 测试用例3:输入{"Z:0", "A:-1"} System.out.println(Output(new String[]{"Z:0", "A:-1"})); // 输出A:-1 } }
核心逻辑说明
- 合并函数
(oldValue, newValue) -> oldValue + newValue是解决重复键异常的核心,遇到相同键时不会抛出错误,而是直接把两个数值累加 - 值格式处理逻辑专门解决整数转Double后出现
6.0这类和示例输出不一致的问题,当值是整数值时直接转为整数格式输出 - 过滤、排序、拼接逻辑完全匹配需求要求的输出规则,所有测试用例运行结果和预期完全一致
内容的提问来源于stack exchange,提问作者jaxij
相关产品推荐
相关产品推荐

