如何使用Java8在HashMaps列表上进行多个聚合
我对java 8实现中HashMap列表的多个聚合有一个问题(首选使用如何使用Java8在HashMaps列表上进行多个聚合,java,java-8,Java,Java 8,我对java 8实现中HashMap列表的多个聚合有一个问题(首选使用“reduce”函数,但不是必须) 我需要使用拆分(“\u”)[0]”“服务”键名进行多个聚合,如下所示: 假设我的数据结构: List<Map<String, Object>> payments = new ArrayList<>(); for(int i=0 ; ....i++){ Map<String, String> map = new HashMap&
“reduce”
函数,但不是必须)
我需要使用拆分(“\u”)[0]”“服务”键名进行多个聚合,如下所示:
假设我的数据结构:
List<Map<String, Object>> payments = new ArrayList<>();
for(int i=0 ; ....i++){
Map<String, String> map = new HashMap<>();
map.put("service","IMAP_"+i);
map.put("storageValue",<some value>)
....
payments.add(map);
}
结果应该是:
{
"payments": [
{
"service": "IMAP",
"storageValue": 30,
"users": "11"
},
{
"storageValue": 400,
"service": "Office 365 Exchange",
"users": "25"
},
{
"storageValue": 50,
"service": "SalesForce",
"users": "100"
}
]
}
应该是
payments.stream().forEach(paymet -> {
paymet.entrySet().stream().map(....?...).reduce()...
);
这里有一个不完整的建议,它将
收集器.groupingBy
与收集器.reduce
结合起来
Map<String,Optional<Map<String,Object>>> result =
payments.stream ().collect(Collectors.groupingBy (map -> map.get ("service").split ("_")[0],
Collectors.reducing ((m1,m2)-> {
Map<String,String> m = new HashMap<>();
m.put("service",m1.get("service")); // you may have to remove the _1 suffix
m.put("storageValue",(Integer)m1.get("storageValue")+(Integer)m2.get("storageValue"));
m.put("users",(Integer)m1.get("users")+(Integer)m2.get("users"));
return m;
})));
映射结果=
payments.stream().collect(Collectors.groupingBy(map->map.get(“服务”).split(“”)[0],
收集器。减少量((m1,m2)->{
Map m=新的HashMap();
m、 put(“service”,m1.get(“service”);//您可能需要删除_1后缀
m、 put(“storageValue”,(整数)m1.get(“storageValue”)+(整数)m2.get(“storageValue”);
m、 put(“users”,(Integer)m1.get(“users”)+(Integer)m2.get(“users”);
返回m;
})));
请注意,由于Map
s包含String
值,因此将这些Map
的值当作数字来添加有点不方便。您必须进行一些从String
到int
的转换,反之亦然
将每个
映射
转换为具有存储、用户和storageValue属性的某个类的实例可能会有所帮助。然后你可以有一个结合两个这样的实例的方法。试试这个。这不是优雅:)
首先将服务
键的值更改为新值
payments.stream()
.forEach(item -> item.put("service", item.get("service").split("_")[0]));
然后
HashMap-mapofmap=payments.stream()
.collect(Collectors.toMap(hashMap->hashMap.get(“服务”),
hashMap->(hashMap)hashMap,
YOURCLASS::merge,HashMap::new);
列表结果=新的ArrayList(mapOfMaps.values());
并定义合并两个贴图的方法,如下所示:
private static HashMap<String, String> merge(HashMap<String, String> map1, HashMap<String, String> map2) {
if (map1.get("service").equals(map2.get("service"))) {
Long storageValue = Long.valueOf(map1.get("storageValue")) + Long.valueOf(map2.get("storageValue"));
map1.put("storageValue", storageValue.toString());
Long users = Long.valueOf(map1.get("users")) + Long.valueOf(map2.get("users"));
map1.put("users", users.toString());
}
return map1;
}
private静态HashMap合并(HashMap-map1、HashMap-map2){
如果(map1.get(“服务”).equals(map2.get(“服务”)){
Long-storageValue=Long.valueOf(map1.get(“storageValue”)+Long.valueOf(map2.get(“storageValue”);
map1.put(“storageValue”,storageValue.toString());
Long users=Long.valueOf(map1.get(“用户”)+Long.valueOf(map2.get(“用户”));
map1.put(“users”,users.toString());
}
返回map1;
}
将其作为对象{“服务”:“IMAP”、“storageValue”:“30”、“用户”:“11”}
,将大大减轻您的生活。@nullpointer您是对的,但不能忽略的是遗留代码changed@VitalyT当然,这是可以改变的。即使您的职责只涉及这一个操作,您最好先将这些映射转换为有意义类的实例,使用这些实例以可维护的方式执行操作,然后将生成的实例转换回映射。但我怀疑这是代码中唯一可以更改的部分。现在,您将要创建更多的“无法更改的遗留代码”。@Eran假设它是一个整数……我只需要自己进行求和实现吗?我可以改用java8sum实现吗?谢谢:)@vitaly我想什么是整数?你地图的价值?在这种情况下,它必须是一个映射
,您需要将值强制转换为整数
,以便执行加法。您是对的,更改为对象…您可以使用求和函数更改答案吗…@vitaly请参见编辑。我没有测试它,所以可能有一些拼写错误。非常感谢,但我想知道我是否可以在java8函数中使用“sum”构建?
HashMap<String, HashMap> mapOfMaps = payments.stream()
.collect(Collectors.toMap(hashMap -> hashMap.get("service"),
hashMap -> (HashMap) hashMap,
YOURCLASS::merge, HashMap::new));
List<HashMap> result = new ArrayList<>(mapOfMaps.values());
private static HashMap<String, String> merge(HashMap<String, String> map1, HashMap<String, String> map2) {
if (map1.get("service").equals(map2.get("service"))) {
Long storageValue = Long.valueOf(map1.get("storageValue")) + Long.valueOf(map2.get("storageValue"));
map1.put("storageValue", storageValue.toString());
Long users = Long.valueOf(map1.get("users")) + Long.valueOf(map2.get("users"));
map1.put("users", users.toString());
}
return map1;
}