I have the following list of maps
List<Map<String, Object>> listBeforeGroup = new ArrayList<Map<String, Object>>();
Map<String, Object> m1 = new HashMap<String, Object>();
m1.put("company", "LG");
m1.put("billType", "A");
m1.put("billPeriod", "09-2018");
Map<String, Object> m2 = new HashMap<String, Object>();
m2.put("company", "LG");
m2.put("billType", "A");
m2.put("billPeriod", "09-2018");
Map<String, Object> m3 = new HashMap<String, Object>();
m3.put("company", "LG");
m3.put("billType", "A");
m3.put("billPeriod", "09-2018");
Map<String, Object> m4 = new HashMap<String, Object>();
m4.put("company", "LG");
m4.put("billType", "B");
m4.put("billPeriod", "01-2019");
Map<String, Object> m5 = new HashMap<String, Object>();
m5.put("company", "LG");
m5.put("billType", "B");
m5.put("billPeriod", "01-2019");
Map<String, Object> m6 = new HashMap<String, Object>();
m6.put("company", "Samsung");
m6.put("billType", "A");
m6.put("billPeriod", "10-2018");
Map<String, Object> m7 = new HashMap<String, Object>();
m7.put("company", "Samsung");
m7.put("billType", "A");
m7.put("billPeriod", "10-2018");
Map<String, Object> m8 = new HashMap<String, Object>();
m8.put("company", "Samsung");
m8.put("billType", "B");
m8.put("billPeriod", "11-2018");
listBeforeGroup.add(m1);listBeforeGroup.add(m2);
listBeforeGroup.add(m3);listBeforeGroup.add(m4);
listBeforeGroup.add(m5);listBeforeGroup.add(m6);
How do I get this output?
//Desired Output - List<Map<String, Object>>
//{company=LG, billType=A, billPeriod=09-2018, count=3}
//{company=LG, billType=B, billPeriod=01-2019, count=2}
//{company=Samsung, billType=A, billPeriod=10-2018, count=2}
//{company=Samsung, billType=B, billPeriod=11-2018, count=1}
I tried this, using java 8 streams, but I can't get the desired output
List<Map<String, Object>> listAfterGroup = listBeforeGroup.stream().map(m -> m.entrySet().stream().collect(Collectors.toMap(p -> p.getKey(), p - > p.getValue()))).collect(Collectors.toList());
And tried this, btw this solution gives a map but I don't want this
Map<Object, Long> listAfterGroup = listBeforeGroup.stream().flatMap(m -> m.entrySet().stream()).collect(Collectors.groupingBy(Map.Entry::getKey,Collectors.counting()));
I want to group the maps by the key "billPeriod" for example, and count items by the values, then generate a new list of maps.
You can create a class Company
and then subsequent operations become much simpler.
class Company {
String company;
String billType;
String billPeriod;
public Company(String company, String billType, String billPeriod) {
this.company = company;
this.billType = billType;
this.billPeriod = billPeriod;
}
// getters, setters, toString, etc
}
Initialize the list :
List<Company> list = new ArrayList<>();
list.add(new Company("LG", "A", "09-2018"));
list.add(new Company("LG", "A", "09-2018"));
list.add(new Company("LG", "A", "09-2018"));
list.add(new Company("LG", "B", "01-2019"));
list.add(new Company("LG", "B", "01-2019"));
list.add(new Company("Samsung", "A", "10-2018"));
list.add(new Company("Samsung", "A", "10-2018"));
list.add(new Company("Samsung", "B", "11-2018"));
Now for an example, you can group by company name :
Map<String, Long> map = list.stream().collect(
Collectors.groupingBy(Company::getCompany,
Collectors.mapping((Company c) -> c, Collectors.counting())));
Now it becomes much easier to perform other operations as you desire. Also, here instead of creating 8 maps you end up dealing with just 1 list.
It's really difficult to grouping and counting a map because your map data will be changed after you increase your counter value. Therefore, you must save the original data of the map, and save your counter value to the another map. Join 2 maps after your counting process is complete.
Map<Map<String, Object>, Long> counterData = listBeforeGroup.stream().collect(Collectors.groupingBy(m -> m, Collectors.counting()));
List<Map<String, Object>> listAfterGroup = new ArrayList<>();
for (Map<String, Object> m : counterData.keySet()) {
Map<String, Object> newMap = new HashMap<>(m);
newMap.put("count", counterData.get(m));
listAfterGroup.add(newMap);
}
Update Java 8 approach, not easy to debug
List<Map<String, Object>> listAfterGroup = listBeforeGroup.stream().collect(Collectors.groupingBy(m -> m, Collectors.counting())).entrySet().stream().map(e -> {
Map<String, Object> newMap = e.getKey();
newMap.put("count", e.getValue());
return newMap;
}).collect(Collectors.toList());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With