Reputation: 101
The Arraylist is like below:
[{
"id": 1,
"parent_id": 0,
"name": "Top1",
}, {
"id": 2,
"parent_id": 1,
"name": "Second Layer1",
},{
"id": 3,
"parent_id": 0,
"name": "Top2",
},{
"id": 4,
"parent_id": 1,
"name": "Second Layer2",
}]
The output should be like:
[{
"id": 1,
"parent_id": 0,
"name": "Top1",
"children": [{
"id": 2,
"parent_id": 1,
"name": "Second Layer1",
}, {
"id": 4,
"parent_id": 1,
"name": "Second Layer2",
}]
}, {
"id": 3,
"parent_id": 0,
"name": "Top2",
}]
My current solution is that distinguishing "top layers" and "second layers", then converting the "second layers" to a hashmap group by "parent_id", finally iterating the "top layers" and match up the id of "top layer" with the key of that hashmap.
The implementation is like blew:
List<Org> topLayers = list.stream().filter(org -> org.getParent_id==0).collect(Collectors.toList());
List<Org> secondLayers = list.stream().filter(org -> org.getParent_id!=0).collect(Collectors.toList());
Map<Long, List<Org>> hashMap = secondLayers.stream().collect(Collectors.groupingBy(Org::parent_id));
topLayers.stream().forEach(topOrg -> {
topOrg.setChildren(hashMap.get(topOrg.getId()));
});
As you could see, it costs 4 steps to figure out.
Is there a more effective way to solve it?
Extension: What if is there more than 2 layers? like recursive
Upvotes: 2
Views: 2782
Reputation: 506
You also can do like this
Map<Long, Org> hashMap = list.stream()
.filter(org -> org.getParent_id!=0)
.collect(Collectors.groupingBy(Org::parent_id));
List<Org> listWithChilds = list.stream()
.filter(org -> org.getParent_id==0)
.map(topOrg -> {
topOrg.addChildren(hashMap.get(topOrg.getId()));
})
.collect(Collectors.toList());
Upvotes: 4
Reputation: 3591
Here is the online demo . you can do this by using forEach
and then useing filter
originalList.forEach(el->{
int parentId = Integer.parseInt(el.get("parent_id").toString());
if(parentId>0) {
List<Map<String, Object>> childList = originalList.stream().filter(e->Integer.parseInt(el.get("id").toString())==parentId).collect(Collectors.toList());
if(!childList.isEmpty()) {
el.put("children",childList );
}
}
});
Upvotes: 1
Reputation: 51
You already said it, recursive.
convert(List src, List target) {
for each item with parent id as (target is empty ? 0 : target's id):
add it to (target is empty ? target : target's children)
convert(src, item)
}
Upvotes: -1
Reputation: 15896
You can simply group all your data using group by based on parentID then assign each parent to that list:
Map<Long, List<Org>> result = list.stream()
.collect(Collectors.groupingBy(Org::parent_id));
then:
list.stream().filter(org -> org.getParent_id==0).forEach(v -> {
v.addChildren(result.get(v.getId()));
});
There can we many way to do this. You can try others too.
Upvotes: 2