如何将地图的地图列表合并为地图的地图?
How to merge List of Maps of Maps into a Map of Maps?
你能帮我 Java Streams
吗?
如标题所示,我需要将 List<Map<String, Map<String, Genuineness>>>
合并到 Map<String, Map<String, Genuineness>>
。
列表表示为 List<Map<String, Map<String, Genuineness>>>
,看起来像:
[
{
"USER_1":{
"APP_1":{
"total":1,
"totalGenuine":1,
"totalDevelopment":1
}
},
"USER_2":{
"APP_1":{
"total":1,
"totalGenuine":1,
"totalDevelopment":1
},
"APP_2":{
"total":2,
"totalGenuine":2,
"totalDevelopment":2
}
}
},
{
"USER_1":{
"APP_1":{
"total":1,
"totalGenuine":1,
"totalDevelopment":1
}
},
"USER_2":{
"APP_1":{
"total":1,
"totalGenuine":1,
"totalDevelopment":1
},
"APP_2":{
"total":2,
"totalGenuine":2,
"totalDevelopment":2
}
}
}
]
因此,如您所见,重复键可能无处不在。
我的目标是通过合并 Genuineness
将它们组合成 Map<String, Map<String, Genuineness>>
。合并 Genuineness
只是意味着 return 一个新的 object 具有汇总值 total
、totalGenuine
和 totalDevelopment
.
这是我失败的实现:
final Map<String, Map<String, Genuineness>> map = taskHandles.stream().map(this::mapTaskHandle)
.flatMap(m -> m.entrySet().stream()).collect(
Collectors.toMap(Map.Entry::getKey, e -> e.getValue().entrySet().stream()
.collect(
Collectors.toMap(Map.Entry::getKey,
g -> new Genuineness(g.getValue().getTotal(), g.getValue().getTotalGenuine(), g.getValue().getTotalDevelopment()),
(g1, g2) -> new Genuineness(g1.getTotal() + g2.getTotal(),
g1.getTotalGenuine() + g2.getTotalGenuine(),
g1.getTotalDevelopment() + g2.getTotalGenuine()
)
)
)
)
);
失败并显示消息:
java.lang.IllegalStateException: Duplicate key {TEST_33_33_APP_1=live.attach.billing.domain.model.billing.Genuineness@951b6fe}
所以,在我的实现中,我似乎指出了如何合并内部地图,但没有合并外部地图的值,我不知道该怎么做。
非常感谢你的帮助。提前致谢!
更新:
预期输出:
{
"USER_1":{
"APP_1":{
"total":2,
"totalGenuine":2,
"totalDevelopment":2
}
},
"USER_2":{
"APP_1":{
"total":2,
"totalGenuine":2,
"totalDevelopment":2
},
"APP_2":{
"total":4,
"totalGenuine":4,
"totalDevelopment":4
}
}
}
老实说,这是一个糟糕的数据结构,代码的维护者将很难发现出现的问题。
你应该退一步考虑重构代码,任何你可以通过在最外层使用以下合并功能来解决缺失部分的方法toMap
:
(l, r) -> {
r.forEach((k, v) -> l.merge(k, v,
(bi, bii) -> new Genuineness(bi.getTotal() + bii.getTotal(),
bi.getTotalGenuine() + bii.getTotalGenuine(),
bi.getTotalDevelopment() + bii.getTotalGenuine())));
return l;
}
完整代码:
taskHandles.stream().map(this::mapTaskHandle)
.flatMap(m -> m.entrySet().stream()).collect(
Collectors.toMap(Map.Entry::getKey, e -> e.getValue().entrySet().stream()
.collect(
Collectors.toMap(Map.Entry::getKey,
g -> new Genuineness(g.getValue().getTotal(), g.getValue().getTotalGenuine(), g.getValue().getTotalDevelopment()),
(g1, g2) -> new Genuineness(g1.getTotal() + g2.getTotal(),
g1.getTotalGenuine() + g2.getTotalGenuine(),
g1.getTotalDevelopment() + g2.getTotalGenuine()
)
)
),(l, r) -> {
r.forEach((k, v) -> l.merge(k, v,
(bi, bii) -> new Genuineness(bi.getTotal() + bii.getTotal(),
bi.getTotalGenuine() + bii.getTotalGenuine(),
bi.getTotalDevelopment() + bii.getTotalGenuine())));
return l;
}
)
);
尽管 seems to be correct, you can alternatively improve your code readability and simplify it defining a BinaryOperator<Genuineness>
作为 :
BinaryOperator<Genuineness> remappingGenuineness = (g1, g2) -> new Genuineness(g1.getTotal() + g2.getTotal(),
g1.getTotalGenuine() + g2.getTotalGenuine(),
g1.getTotalDevelopment() + g2.getTotalGenuine()
);
然后进一步将其用作:
final Map<String, Map<String, Genuineness>> map = taskHandles.stream()
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey,
e -> e.getValue().entrySet().stream().collect(
Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, remappingGenuineness)),
(a, b) -> {
a.forEach((k, v) -> b.merge(k, v, remappingGenuineness));
return b;
}));
你能帮我 Java Streams
吗?
如标题所示,我需要将 List<Map<String, Map<String, Genuineness>>>
合并到 Map<String, Map<String, Genuineness>>
。
列表表示为 List<Map<String, Map<String, Genuineness>>>
,看起来像:
[
{
"USER_1":{
"APP_1":{
"total":1,
"totalGenuine":1,
"totalDevelopment":1
}
},
"USER_2":{
"APP_1":{
"total":1,
"totalGenuine":1,
"totalDevelopment":1
},
"APP_2":{
"total":2,
"totalGenuine":2,
"totalDevelopment":2
}
}
},
{
"USER_1":{
"APP_1":{
"total":1,
"totalGenuine":1,
"totalDevelopment":1
}
},
"USER_2":{
"APP_1":{
"total":1,
"totalGenuine":1,
"totalDevelopment":1
},
"APP_2":{
"total":2,
"totalGenuine":2,
"totalDevelopment":2
}
}
}
]
因此,如您所见,重复键可能无处不在。
我的目标是通过合并 Genuineness
将它们组合成 Map<String, Map<String, Genuineness>>
。合并 Genuineness
只是意味着 return 一个新的 object 具有汇总值 total
、totalGenuine
和 totalDevelopment
.
这是我失败的实现:
final Map<String, Map<String, Genuineness>> map = taskHandles.stream().map(this::mapTaskHandle)
.flatMap(m -> m.entrySet().stream()).collect(
Collectors.toMap(Map.Entry::getKey, e -> e.getValue().entrySet().stream()
.collect(
Collectors.toMap(Map.Entry::getKey,
g -> new Genuineness(g.getValue().getTotal(), g.getValue().getTotalGenuine(), g.getValue().getTotalDevelopment()),
(g1, g2) -> new Genuineness(g1.getTotal() + g2.getTotal(),
g1.getTotalGenuine() + g2.getTotalGenuine(),
g1.getTotalDevelopment() + g2.getTotalGenuine()
)
)
)
)
);
失败并显示消息:
java.lang.IllegalStateException: Duplicate key {TEST_33_33_APP_1=live.attach.billing.domain.model.billing.Genuineness@951b6fe}
所以,在我的实现中,我似乎指出了如何合并内部地图,但没有合并外部地图的值,我不知道该怎么做。
非常感谢你的帮助。提前致谢!
更新: 预期输出:
{
"USER_1":{
"APP_1":{
"total":2,
"totalGenuine":2,
"totalDevelopment":2
}
},
"USER_2":{
"APP_1":{
"total":2,
"totalGenuine":2,
"totalDevelopment":2
},
"APP_2":{
"total":4,
"totalGenuine":4,
"totalDevelopment":4
}
}
}
老实说,这是一个糟糕的数据结构,代码的维护者将很难发现出现的问题。
你应该退一步考虑重构代码,任何你可以通过在最外层使用以下合并功能来解决缺失部分的方法toMap
:
(l, r) -> {
r.forEach((k, v) -> l.merge(k, v,
(bi, bii) -> new Genuineness(bi.getTotal() + bii.getTotal(),
bi.getTotalGenuine() + bii.getTotalGenuine(),
bi.getTotalDevelopment() + bii.getTotalGenuine())));
return l;
}
完整代码:
taskHandles.stream().map(this::mapTaskHandle)
.flatMap(m -> m.entrySet().stream()).collect(
Collectors.toMap(Map.Entry::getKey, e -> e.getValue().entrySet().stream()
.collect(
Collectors.toMap(Map.Entry::getKey,
g -> new Genuineness(g.getValue().getTotal(), g.getValue().getTotalGenuine(), g.getValue().getTotalDevelopment()),
(g1, g2) -> new Genuineness(g1.getTotal() + g2.getTotal(),
g1.getTotalGenuine() + g2.getTotalGenuine(),
g1.getTotalDevelopment() + g2.getTotalGenuine()
)
)
),(l, r) -> {
r.forEach((k, v) -> l.merge(k, v,
(bi, bii) -> new Genuineness(bi.getTotal() + bii.getTotal(),
bi.getTotalGenuine() + bii.getTotalGenuine(),
bi.getTotalDevelopment() + bii.getTotalGenuine())));
return l;
}
)
);
尽管 BinaryOperator<Genuineness>
作为 :
BinaryOperator<Genuineness> remappingGenuineness = (g1, g2) -> new Genuineness(g1.getTotal() + g2.getTotal(),
g1.getTotalGenuine() + g2.getTotalGenuine(),
g1.getTotalDevelopment() + g2.getTotalGenuine()
);
然后进一步将其用作:
final Map<String, Map<String, Genuineness>> map = taskHandles.stream()
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey,
e -> e.getValue().entrySet().stream().collect(
Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, remappingGenuineness)),
(a, b) -> {
a.forEach((k, v) -> b.merge(k, v, remappingGenuineness));
return b;
}));