如何将地图地图列表合并到地图中?

Pav*_*vel 7 java hashmap java-stream collectors

你能帮帮我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
         }
      }
   }
]
Run Code Online (Sandbox Code Playgroud)

因此,正如您所看到的,重复的键可能无处不在.我的目标是Map<String, Map<String, Genuineness>>通过合并将它们组合在一起Genuineness.合并Genuineness只是意味着返回一个新的对象与总结了值total,totalGenuinetotalDevelopment.

这是我的实现失败:

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()
                                                )
                                        )
                                )
                        )
                );
Run Code Online (Sandbox Code Playgroud)

它失败并带有消息:

java.lang.IllegalStateException: Duplicate key {TEST_33_33_APP_1=live.attach.billing.domain.model.billing.Genuineness@951b6fe}
Run Code Online (Sandbox Code Playgroud)

所以,似乎在我的实现中我已经指出了如何组合内部地图但没有合并外部地图的值,我不知道该怎么做.

我非常感谢你的帮助.先感谢您!

更新:预期输出:

   {  
      "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
         }
      }
   }
Run Code Online (Sandbox Code Playgroud)

Ous*_* D. 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;
}
Run Code Online (Sandbox Code Playgroud)

完整代码:

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;
                                }

                        )
                );
Run Code Online (Sandbox Code Playgroud)

伊迪奥内