我在一张Map里面有一张Map,看起来像这样:
Map<String, Map<Integer, BigDecimal>> mapInMap; //--> with values like:
/*
"a": (1: BigDecimal.ONE),
"b": (2: BigDecimal.TEN),
"c": (1: BigDecimal.ZERO)
* /
我希望通过期望得到以下结果来组合内部Map:
Map<Integer, BigDecimal> innerMapCombined; //--> with values:
/*
1: BigDecimal.ZERO,
2: BigDecimal.TEN
* /
这是我的解决方案,通过预定义组合Map并使用foreach:
Map<Integer, BigDecimal> combined = new HashMap<>();
mapInMap.forEach((str, innerMap) -> {
innerMap.forEach(combined::putIfAbsent);
});
但这将忽略 (1: BigDecimal.ZERO)
.
你能用Java8流提供一个单线解决方案吗?
2条答案
按热度按时间jgzswidk1#
问题是,只要初始化Map并在内部Map上添加重复的键,就会重写这些键,因为这些Map不接受重复的键。因此,您需要首先更改以下内容:
到
Map
允许复制密钥,例如google guava的multimap:内部贴图的创建方式如下:
只有现在您才能尝试使用Java8StreamsAPI来解决您的问题。例如:
使用的mergefunction参数解决了重复密钥冲突
toMap
方法。我们明确表示取第二个值(v1, v2) -> v2
如果是重复的。svmlkihl2#
问题:
解决当前解决方案不起作用的原因是
Map#putIfAbsent
方法仅添加Map中已存在的值,而不替换该值。解决方案用于:
Map#put
是一种方法,但是它的局限性在于,您无法决定是否要始终保留此类键的第一个值、计算新值还是始终使用最后一个值。因此,我建议使用Map#computeIfPresent
以及Map#putIfAbsent
或者最好是一种同时完成所有任务的方法Map#merge(K, V, BiFunction)
用一个BiFunction remappingFunction
:remappingfunction—如果存在值,则重新计算该值的函数
使用流api的解决方案:
在类似流的解决方案中重写它,方法是相同的。唯一的区别是streamapi的声明性语法,然而,其思想是非常相同的。
只需平面Map结构并收集到一个带有
Collector.toMap(Function, Function, BinaryOperator
使用BinaryOperator mergeFunction
合并重复的键。mergefunction—一个合并函数,用于解决与同一键相关的值之间的冲突,如提供给map.merge(object,object,bifunction)的那样
注意:@dreamcrash在速度方面的出色的streamapi回答也值得称赞。
结果:
{1=1, 2=10}
结果是当你弹出这样的Map(注意BigDecimal
打印为数字)。此输出与预期输出匹配。请注意
Map#merge(K, V, BiFunction)
以及Collector.toMap(Function, Function, BinaryOperator
使用非常相似的方法得到相同的结果。