java - 按值分组地图列表并通过排序合并为分组列表
问题描述
我想按值对地图列表进行分组,并在某些条件下将插入(合并)作为分组列表。按值“yr”分组并按相同“类别”合并“标签”,然后将“价格”汇总在一起,然后按“价格”降序排列
List<Grocery> groceryList = new ArrayList<>();
Grocery grocery = new Grocery();
List<HahsMap<String, Object>> tagList = new ArrayList<>();
HashMap<String, Object> tagMap = new HashMap<>();
## feeding data example
tagMap.put("category", "A");
tagMap.put("name", "Apple");
tagMap.put("price", 10);
tagList.add(tagMap);
grocery.setYr(String yr);
grocery.setTag(List<Hashmap<String, Object>> tagList);
groceryList.add(grocery);
这是地图列表的示例。
List<Grocery> groceryList =
[
{
"yr": "2021",
"tag": [
{
"Category": "A",
"Name": "Apple",
"Price": 10
}
]
},
{
"yr": "2021",
"tag": [
{
"Category": "A",
"Name": "Apple",
"Price": 10
}
]
},
{
"yr": "2021",
"tag": [
{
"Category": "B",
"Name": "Banana",
"Price": 5
}
]
},
{
"yr": "2020",
"tag": [
{
"Category": "A",
"Name": "Apple",
"Price": 10
}
]
},
{
"yr": "2020",
"tag": [
{
"Category": "B",
"Name": "Banana",
"Price": 30
}
]
},
{
"yr": "2020",
"tag": [
{
"Category": "C",
"Name": "Candy",
"Price": 10
}
]
},
{
"yr": "2020",
"tag": [
{
"Category": "C",
"Name": "Candy",
"Price": 30
}
]
},
{
"yr": "2020",
"tag": [
{
"Category": "A",
"Name": "Apple",
"Price": 10
}
]
}
]
这是我想要得到的示例输出
List<Grocery> result =
[
{
"yr": "2021",
"tag": [
{
"Category": "A",
"Name": "Apple",
"Price": 20
},
{
"Category": "B",
"Name": "Banada",
"Price": 5
}
]
},
{
"yr": "2020",
"tag": [
{
"Category": "C",
"Name": "Candy",
"Price": 40
},
{
"Category": "B",
"Name": "Banada",
"Price": 30
},
{
"Category": "A",
"Name": "Apple",
"Price": 20
}
]
}
]
我知道将所有条件合二为一很棘手,有人可以帮我吗?如果至少我能对此有一些想法,那将不胜感激。
我尝试先将它们分组为“年”,然后尝试找到要映射的值,然后用相同的“类别”对它们进行排序,然后总结..但我不知道对它们进行排序并将它们与 summed 合并在一起涨价。。
提前致谢!!
解决方案
请检查这是否是您要查找的内容。
String inputJson = "[{\"yr\":\"2021\",\"tag\":[{\"Category\":\"A\",\"Name\":\"Apple\",\"Price\":10}]},{\"yr\":\"2021\",\"tag\":[{\"Category\":\"A\",\"Name\":\"Apple\",\"Price\":10}]},{\"yr\":\"2021\",\"tag\":[{\"Category\":\"B\",\"Name\":\"Banana\",\"Price\":5}]},{\"yr\":\"2020\",\"tag\":[{\"Category\":\"A\",\"Name\":\"Apple\",\"Price\":10}]},{\"yr\":\"2020\",\"tag\":[{\"Category\":\"B\",\"Name\":\"Banana\",\"Price\":30}]},{\"yr\":\"2020\",\"tag\":[{\"Category\":\"C\",\"Name\":\"Candy\",\"Price\":10}]},{\"yr\":\"2020\",\"tag\":[{\"Category\":\"C\",\"Name\":\"Candy\",\"Price\":30}]},{\"yr\":\"2020\",\"tag\":[{\"Category\":\"A\",\"Name\":\"Apple\",\"Price\":10}]}]";
ObjectMapper objectMapper = new ObjectMapper();
//convert json to input Grocery List using jackson object mapper
List<Grocery> groceries = objectMapper.readValue(inputJson, new TypeReference<List<Grocery>>() {
});
List<Grocery> output = new ArrayList<>();
//group all groceries by year
Map<String, List<Grocery>> groceriesByYear = groceries.stream().collect(Collectors.groupingBy(grocery -> grocery.getYr()));
groceriesByYear.keySet().forEach(year -> {
//for each year, get the grocery list
List<Grocery> groceryList = groceriesByYear.get(year);
//merge tags which have same category
Map<String, Tag> tagsPerCategory = groceryList.stream().flatMap(grocery -> grocery.getTag().stream()).collect(Collectors.toMap(Tag::getCategory, Function.identity(),
(tag1, tag2) -> {
//merge function, sum up the price of tag which has same category
tag1.setPrice(tag1.getPrice() + tag2.getPrice());
return tag1;
}));
//create new grocery object with required data
Grocery grocery = new Grocery();
grocery.setYr(year);
grocery.setTag(new ArrayList<>(tagsPerCategory.values()));
output.add(grocery);
});
//output list will have groceries grouped by year and tag with summed up price
编辑
您可以对标签流进行过滤以避免空标签对象,如果您认为价格可以为空,则可以添加非空检查,或者如果尚未设置价格,则可以定义一种方法来提供默认值,如下所示
public static <T> T getValueOrDefault(T value, T defaultValue) {
return value != null ? value : defaultValue;
}
你的 tagsPerCategory 看起来像下面
Map<String, Tag> tagsPerCategory = groceryList.stream().flatMap(grocery -> grocery.getTag().stream()).filter(tag -> tag != null && tag.getPrice() != null)
.collect(Collectors.toMap(Tag::getCategory, Function.identity(),
(tag1, tag2) -> {
//sum up the price of tag which has same category
tag1.setPrice(getValueOrDefault(tag1.getPrice(), 0) + getValueOrDefault(tag2.getPrice(), 0));
return tag1;
}));
推荐阅读
- javascript - 如何在 react native 中将值从 promise 传递给组件 prop?
- c# - 从 .net core 2.2 迁移到 .net core 3.0 后打破视图
- java - Hibernate 注释:具有共享复合键属性的多对多
- php - 如何在 yii2 中返回数组值?
- dotnetnuke - DNN 站点在 dot net nuke 版本中运行缓慢 - 9.4.1
- file - 新创建的 Flutter App 的文件夹和文件说明?
- python - 根据多个条件过滤行
- prometheus-alertmanager - 进程使用过多 CPU 时,prometheus 中带有警报规则的进程导出器
- javascript - /static/ 的位置在设置 app.route(/something/) 时更改为 /something/static/
) - android - 失败的 sepolicy 检查 - Android 10 构建 - Pixel 3a XL