问题:
要解决您当前的解决方案不起作用的原因是因为 Map#putIfAbsent 方法仅添加而不替换映射中已经存在的值。
使用 for-each 的解决方案:
Map#put 是一种可行的方法,但它的局限性在于您无法决定是否要始终保留此类键的第一个值、计算新值或始终使用最后一个值。出于这个原因,我建议使用Map#computeIfPresent 和Map#putIfAbsent 的组合或更好的方法,即Map#merge(K, V, BiFunction) 和BiFunction remappingFunction:
remappingFunction - 重新计算值(如果存在)的函数
Map<Integer, BigDecimal> resultMap = new HashMap<>();
for (Map<Integer, BigDecimal> map: mapInMap.values()) {
for (Map.Entry<Integer, BigDecimal> entry: map.entrySet()) {
resultMap.merge(entry.getKey(), entry.getValue(), (l, r) -> r);
}
}
使用 Stream API 的解决方案:
要在 Stream-alike 解决方案中重写它,方法是相同的。唯一的区别是 Stream API 的声明式语法,但是思路是一样的。
只需对结构进行平面映射,然后使用BinaryOperator mergeFunction 将重复的键合并到带有Collector.toMap(Function, Function, BinaryOperator 的映射。
mergeFunction - 一个合并函数,用于解决与同一键关联的值之间的冲突,提供给 Map.merge(Object, Object, BiFunction)
Map<Integer, BigDecimal> resultMap = mapInMap.values().stream()
.flatMap(entries -> entries.entrySet().stream())
.collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (l, r) -> r));
注意:@dreamcrash 在速度方面的出色 Stream API answer 也值得称赞。
结果:
{1=1, 2=10} 是您打印出此类地图时的结果(请注意,BigDecimal 打印为数字)。此输出与您的预期输出匹配。
1=BigDecimal.ZERO
2=BigDecimal.TEN
注意Map#merge(K, V, BiFunction) 和Collector.toMap(Function, Function, BinaryOperator 之间的相似之处,它们使用非常相似的方法来获得相同的结果。