Java 如何用流替换LinkedhashMap和HashMap?
你能帮我把地图分类吗 我有下面的结构,我想在Java 如何用流替换LinkedhashMap和HashMap?,java,lambda,java-stream,linkedhashmap,collectors,Java,Lambda,Java Stream,Linkedhashmap,Collectors,你能帮我把地图分类吗 我有下面的结构,我想在LinkedHashMap中按值的相反顺序在customers下组装应用程序 [{ "CUSTOMER_1": { "APP_1": "1" }, "CUSTOMER_2": { "APP_1": "2", "APP_3": "7", "APP_2": "3" } }] 我已经有了组装地图的lambda: final Map<String, Map<String, Long>>
LinkedHashMap
中按值的相反顺序在customers下组装应用程序
[{
"CUSTOMER_1": {
"APP_1": "1"
},
"CUSTOMER_2": {
"APP_1": "2",
"APP_3": "7",
"APP_2": "3"
}
}]
我已经有了组装地图的lambda:
final Map<String, Map<String, Long>> organizationApps = taskHandles.stream().map(this::mapPayload)
.flatMap(e -> e.entrySet().stream())
.collect(groupingBy(Map.Entry::getKey, of(HashMap::new,
(r, t) -> t.getValue().forEach((k, v) -> r.merge(k, v, Long::sum)),
(r1, r2) -> {
r2.forEach((v1, v2) -> r1.merge(v1, v2, Long::sum));
return r1;
}))
);
如何在一个lambda中完成此操作?在创建按结果值排序的
LinkedHashMap之前,您无法避免将值收集到映射中,但您可以将转换步骤指定为自定义收集器的finisher函数:
Map<String, Map<String, Long>> organizationApps = input.stream()
.flatMap(e -> e.entrySet().stream())
.collect(groupingBy(Map.Entry::getKey, Collector.of(HashMap::new,
(r, t) -> t.getValue().forEach((k, v) -> r.merge(k, v, Long::sum)),
(r1, r2) -> {
r2.forEach((v1, v2) -> r1.merge(v1, v2, Long::sum));
return r1;
},
(Map<String, Long> m) -> m.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2,
LinkedHashMap::new))
)));
Map organizationApps=input.stream()
.flatMap(e->e.entrySet().stream())
.collect(groupby)(Map.Entry::getKey,Collector.of)(HashMap::new,
(r,t)->t.getValue().forEach((k,v)->r.merge(k,v,Long::sum)),
(r1,r2)->{
r2.forEach((v1,v2)->r1.merge(v1,v2,Long::sum));
返回r1;
},
(映射m)->m.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.collect(toMap(Map.Entry::getKey,Map.Entry::getValue,(e1,e2)->e2,
LinkedHashMap::新建)
)));
这相当于以下(Java9+)代码
Map organizationApps=input.stream()
.flatMap(m->m.entrySet().stream())
.collect(groupingBy)(Map.Entry::getKey,collectingAndThen(flatMapping(
t->t.getValue().entrySet().stream(),
toMap(Map.Entry::getKey,Map.Entry::getValue,Long::sum)),
(映射m)->m.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.collect(toMap(Map.Entry::getKey,Map.Entry::getValue,(e1,e2)->e2,
LinkedHashMap::新建)
)));
最后是与Java 8兼容的flatMapping
收集器的实现,但您的自定义收集器也会执行此任务。在创建按结果值排序的LinkedHashMap
之前,您无法避免将值收集到映射中,但您可以将转换步骤指定为自定义收集器的finisher函数:
Map<String, Map<String, Long>> organizationApps = input.stream()
.flatMap(e -> e.entrySet().stream())
.collect(groupingBy(Map.Entry::getKey, Collector.of(HashMap::new,
(r, t) -> t.getValue().forEach((k, v) -> r.merge(k, v, Long::sum)),
(r1, r2) -> {
r2.forEach((v1, v2) -> r1.merge(v1, v2, Long::sum));
return r1;
},
(Map<String, Long> m) -> m.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2,
LinkedHashMap::new))
)));
Map organizationApps=input.stream()
.flatMap(e->e.entrySet().stream())
.collect(groupby)(Map.Entry::getKey,Collector.of)(HashMap::new,
(r,t)->t.getValue().forEach((k,v)->r.merge(k,v,Long::sum)),
(r1,r2)->{
r2.forEach((v1,v2)->r1.merge(v1,v2,Long::sum));
返回r1;
},
(映射m)->m.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.collect(toMap(Map.Entry::getKey,Map.Entry::getValue,(e1,e2)->e2,
LinkedHashMap::新建)
)));
这相当于以下(Java9+)代码
Map organizationApps=input.stream()
.flatMap(m->m.entrySet().stream())
.collect(groupingBy)(Map.Entry::getKey,collectingAndThen(flatMapping(
t->t.getValue().entrySet().stream(),
toMap(Map.Entry::getKey,Map.Entry::getValue,Long::sum)),
(映射m)->m.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.collect(toMap(Map.Entry::getKey,Map.Entry::getValue,(e1,e2)->e2,
LinkedHashMap::新建)
)));
最后是一个兼容Java 8的flatMapping
收集器的实现,但是您的自定义收集器也可以完成这项工作。这里有一个相关的问题:。重要的是,你需要在收集之前对你的流进行适当的排序。嗨,Ryan!我想我需要在组装映射后对其进行排序,因为最初我可以有两个列表,其中包含具有重复键的映射,我通过求和值来合并映射。我有以下问题:为什么需要在一个lambda中执行此操作?即使这是可能的,你可能会有真正大而丑陋的代码和平。我已经很难理解你的代码中发生了什么。IMHO lambda并不总是解决此类问题的最佳方案。如前所述,lambdas应该是一种表达,而不是一种叙述。尽管lambdas的语法简洁,但它应该准确地表达它们提供的功能。1)因为我想查看结果并将其与以下内容进行比较2)我想了解更多关于lambdas的知识可能有一些不同的方法来组织操作,但最终,在排序之前,您需要应用程序的合并/求和结果,因此我认为它将始终需要(至少)两个逻辑步骤。重要的是,你需要在收集之前对你的流进行适当的排序。嗨,Ryan!我想我需要在组装映射后对其进行排序,因为最初我可以有两个列表,其中包含具有重复键的映射,我通过求和值来合并映射。我有以下问题:为什么需要在一个lambda中执行此操作?即使这是可能的,你可能会有真正大而丑陋的代码和平。我已经很难理解你的代码中发生了什么。IMHO lambda并不总是解决此类问题的最佳方案。如前所述,lambdas应该是一种表达,而不是一种叙述。尽管lambdas的语法简洁,但它应该准确地表达它们提供的功能。1)因为我想查看结果并将其与以下内容进行比较2)我想了解更多关于lambdas的知识可能有一些不同的方法来组织操作,但最终你需要应用程序合并/求和的结果,然后才能进行排序,所以我认为它总是需要(至少)两个逻辑步骤。谢谢你,这正是我想要的!谢谢,那正是我想要的!
Map<String, Map<String, Long>> organizationApps = input.stream()
.flatMap(m -> m.entrySet().stream())
.collect(groupingBy(Map.Entry::getKey, collectingAndThen(flatMapping(
t -> t.getValue().entrySet().stream(),
toMap(Map.Entry::getKey, Map.Entry::getValue, Long::sum)),
(Map<String, Long> m) -> m.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2,
LinkedHashMap::new))
)));