我有一个列表
,例如:
Map<String, String> m1 = new HashMap<>();
m1.put("date", "2020.1.5");
m1.put("B", "10");
Map<String, String> m2 = new HashMap<>();
m2.put("date", "2020.1.5");
m2.put("A", "20");
Map<String, String> m3 = new HashMap<>();
m3.put("date", "2020.1.6");
m3.put("A", "30");
Map<String, String> m4 = new HashMap<>();
m4.put("date", "2020.1.7");
m4.put("C", "30");
List<Map<String, String>> before = new ArrayList<>();
before.add(m1);
before.add(m2);
before.add(m3);
before.add(m4);
我的预期结果是生成一个新的列表映射,它按日期分组,并且在相同日期中设置的所有条目将被放在一起,如:
[{"A":"20","B":"10","date":"2020.1.5"},{"A":"30","date":"2020.1.6"},{"C":"30","date":"2020.1.7"}]
我尝试了下面的方法,但总是没有达到我预期的结果。
stream().flatmap().collect(Collectors.groupingBy())
此问题的一些附加注释:
我用for循环解决了这个问题,但是当列表大小为50000左右时,应用程序会挂起,所以我寻求一种性能更好的方法来实现这一点。 据我所知,Java 8溪流平原地图也许是一条路。 因此,关键的一点不仅是重新映射,而且是用一种性能最好的方法来实现这一点。
before
.stream()
.collect(Collectors.toMap((m) -> m.get("date"), m -> m, (a,b) -> {
Map<String, String> res = new HashMap<>();
res.putAll(a);
res.putAll(b);
return res;
}))
.values();
这就是你要找的解决方案。
tomap
函数接收3个参数:
输出:
[{date=2020.1.5, A=20, B=10}, {date=2020.1.6, A=30}, {date=2020.1.7, C=30}]
您可以使用一定数量的收集器按顺序实现同样的结果:
Collectors.GroupingBy
按日期分组收集器。减少
以合并映射
项Collectors.CollectingandThen
将值从Map>
转换为最终输出List>
。List<Map<String, String>> list = before.stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(
m -> m.get("date"),
Collectors.reducing((l, r) -> {
l.putAll(r);
return l; })
),
o -> o.values().stream()
.flatMap(Optional::stream)
.collect(Collectors.toList())));
列表
包含您要查找的内容:
[{date=2020.1.5,a=20,b=10},{date=2020.1.6,a=30},{date=2020.1.7,c=30}]
重要提示:此解决方案有两个缺点:
列表>中的原始映射;
之前。
可以这样做:
List<Map<String, String>> remapped = before.stream()
.collect(Collectors.groupingBy(m -> m.get("date")))
.values().stream()
.map(e -> e.stream()
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (x1, x2) -> x1)))
.collect(Collectors.toList());
remapped.forEach(System.out::println);
输出:
{date=2020.1.5, A=20, B=10}
{date=2020.1.6, A=30}
{date=2020.1.7, C=30}