如何高效合并List中同键的StringInteger对象?
问题描述
我有一个包含StringInteger对象的List集合(StringInteger是仅包含String类型key和int类型value的POJO),集合内容如下:
List<StringInteger> test = new ArrayList<>(); test.add(new StringInteger("a", 1)); test.add(new StringInteger("b", 1)); test.add(new StringInteger("a", 3)); test.add(new StringInteger("c", 1)); test.add(new StringInteger("a", 1)); test.add(new StringInteger("c", -1)); System.out.println(test); // [{ a : 1 }, { b : 1 }, { a : 3 }, { c : 1 }, { a : 1 }, { c : -1 }]
需要实现按key合并对象并累加对应value的功能,最终得到结果列表:[{ a : 5 }, { b : 1 }, { c : 0 }]。
我已经用HashMap实现了该功能,但步骤比较繁琐,想找更简洁优雅的方案,本来想尝试用Stream API的flatMap,但不知道怎么操作。以下是我当前的实现代码:
Map<String, Integer> map = new HashMap<>(); for (StringInteger stringInteger : test) { if (map.containsKey(stringInteger.getKey())) { int previousValue = map.get(stringInteger.getKey()); map.put(stringInteger.getKey(), previousValue + stringInteger.getValue()); } else { map.put(stringInteger.getKey(), stringInteger.getValue()); } } List<StringInteger> result = map.entrySet() .stream() .map(stringIntegerEntry -> new StringInteger(stringIntegerEntry.getKey(), stringIntegerEntry.getValue())) .collect(Collectors.toList()); System.out.println(result); // [{ a : 5 }, { b : 1 }, { c : 0 }]
简洁实现方案
方案一:使用Collectors.toMap直接聚合
利用Collectors.toMap的第三个参数(合并函数),一步完成分组累加,再转换为目标List:
List<StringInteger> result = test.stream() .collect(Collectors.toMap( StringInteger::getKey, // 提取key作为Map的键 StringInteger::getValue, // 提取value作为Map的初始值 Integer::sum // 相同key时,累加两个value )) .entrySet() .stream() .map(entry -> new StringInteger(entry.getKey(), entry.getValue())) .collect(Collectors.toList());
方案二:使用Collectors.groupingBy配合summingInt
先按key分组,再对每组的value求和,最后转换为目标对象:
List<StringInteger> result = test.stream() .collect(Collectors.groupingBy( StringInteger::getKey, Collectors.summingInt(StringInteger::getValue) // 对每组的value求和 )) .entrySet() .stream() .map(entry -> new StringInteger(entry.getKey(), entry.getValue())) .collect(Collectors.toList());
关于flatMap的说明
flatMap的作用是将每个元素拆分为多个元素后扁平化处理,并不适合这种分组聚合的场景。上面两种Stream方案都是针对分组求和场景的最优实现,代码简洁且可读性强。
内容的提问来源于stack exchange,提问作者user3280842
相关产品推荐
相关产品推荐

