There's a JSON array response I am getting as below.
[{
contracted: 1
payrolltype: basicsalary
otherdata: sampledata
salary: 1000
},{
contracted: 1
payrolltype: basicsalary
otherdata: sampledata
salary: 1001
},{
contracted: 2
payrolltype: basicsalary
otherdata: sampledata
salary: 10002
},
{
contracted: 1
payrolltype: addon
otherdata: sampledata
salary: 1004
}]
I want to structure this data in the form of Map<String, Map<String,List<SalaryMapper>>>
First, I needed to arrange the data by contractId
with the List of Object mapped with the objects where contractId
field is common.
For this, I have used java stream as given:
List<SalaryMapper> salMap = myArray;
Map<String, List<SalaryMapper>> map = salMap.stream().collect(Collectors.groupingBy(SalaryMapper::getContractId));
Now I am getting the result grouped by contractId
. And I am trying to group the map to another level by payrollType
: Map<contractId, Map<payrollType, List<SalaryMapper>>>
.
For this, I tried to iterate the main map and push it to Map<contractId, Map<payrollType, List<SalaryMapper>>>
object, but I am getting lost here.
Map<String, Map<String,List<SalaryMapper>>> subMap = null;
Map<String,List<SalaryMapper>> newMapForPayrollType = null;
for(Map.Entry<String, List<SalaryMapper>> entry : map.entrySet()) {
}
return subMap;
CodePudding user response:
You can do nested level groupingBy by passingdownstream Collector
to do a secondary groupingBy
Map<Integer, Map<String, List<SalaryMapper>>> map = salMap.stream()
.collect(Collectors.groupingBy(SalaryMapper::getContractId,
Collectors.groupingBy(SalaryMapper::getPayrollType)));
As per the data shown in above the contractid
is of Integer
type and payrolltype
is String
, more examples can be found here
CodePudding user response:
The naive approach to your question would be as below:
Map<String, Map<String, List<SalaryMapper>>> subMap = new HashMap<>();
for (SalaryMapper sal: salMap) {
Map<String, List<SalaryMapper>> payrollTypeMap = new HashMap<>();
if (subMap.containsKey(sal.getContractId()) {
payrollTypeMap = subMap.get(sal.getContractId());
if (payrollTypeMap.containsKey(sal.getPayrollType())) {
payrollTypeMap.put(sal.getPayrollType(), payrollTypeMap.get(sal.getPayrollType()).add(sal));
} else {
payrollTypeMap.put(sal.getPayrollType(), new ArrayList<>(){{add(sal);}};
}
} else {
payrollTypeMap.put(sal.getPayrollType(), new ArrayList<>(){{add(sal);}};
}
subMap.put(sal.getContractId(), payrollTypeMap);
}
Above code can be optimized and written with fewer lines of code as below:
Map<Integer, Map<String, List<SalaryMapper>>> subMap = salMap.stream()
.collect(Collectors.groupingBy(SalaryMapper::getContractId,
Collectors.groupingBy(SalaryMapper::getPayrollType)));