Need to convert list of data into list of list based on parent child relationship

Abdul :

I need to convert list of data into list of list based on parent child relationship. If parent is null fall on to level one, level two will be based level one id.

My Data looks like below:

[
    {id:1, parent: null },
    {id:2, parent: 1 },
    {id:3, parent: 1 },
    {id:4, parent: 1 },
    {id:5, parent: 2 },
    {id:6, parent: 2 },
    {id:7, parent: 3 },
    {id:8, parent: 3 },
    {id:9, parent: 4 },
    {id:10, parent: 4 },
    {id:11, parent: 5 },
    {id:12, parent: null },
    {id:13, parent: 12 },
]

My code is:

ResponseData

Map<String,Map<String,ResponseData>> map = new HashMap<>();
for (ResponseData responseData : responseDataList) {
    Map<String,responseData> responseDatasMap =  map.get(responseData.getParent());
    if(responseDatasMap != null) {
        responseDatasMap.put(responseData.getId(),responseData);
        map.put(responseData.getParent(),responseDatasMap);
    } else {
        responseDatasMap =  new HashMap<>();
        responseDatasMap.put(responseData.getParent(),responseData);
        map.put(responseData.getParent(),responseDatasMap);
    }
}

Above map will contain parent as key and map of values mapped to parent

List<List<ResponseData>> sections = new ArrayList<>();
for (Map.Entry<String,Map<String, ResponseData>> responseDataMap : map.entrySet()) {
    Map<String, ResponseData> valueMap = responseDataMap.getValue();
    responseDataList = new ArrayList<>();
    for(Map.Entry<String, ResponseData> responseData :valueMap.entrySet()) {
        responseDataList.add(responseData.getValue());
    }
    sections.add(responseDataList);
}

My output looks like below :

[
    [ {id:1, parent: null } ],
    [ {id:2, parent: 1 },{id:3, parent: 1 },{id:4, parent: 1 } ],
    [ {id:5, parent: 2 },{id:6, parent: 2 } ],
    [ {id:7, parent: 3 },{id:8, parent: 3 } ],
    [ {id:9, parent: 4 },{id:10, parent: 4 } ],
    [ {id:11, parent: 5 }]
]

but My expected output required like below:

First level array contains the data where parent is null

Second level contains the children of level 1 ie id 2,3,4 are a child of id 1

Third level contains the children of levlel2 objects ie 5 & 6 are a child of 2 , 7 & 8 are a child of 3 and 9 & 10 child of 4

Level four contains the children of level 3 objects ie 11 is a child of id 5

[
    [ {id:1, parent: null }, {id:12, parent:null} ],
    [ {id:2, parent: 1 },{id:3, parent: 1 },{id:4, parent: 1 },{id:13, parent: 12 } ],
    [ {id:5, parent: 2 },{id:6, parent: 2 },{id:7, parent: 3 },{id:8, parent: 3 },{id:9, parent: 4 },{id:10, parent: 4 } ],
    [ {id:11, parent: 5 }]
]

Please check and let me know how we can implement the same. Thanks in advance

Ondra K. :

For representing the tree structure, I have used an ArrayList, where the index of the node is equal to its index in the array + 1. If you have a sparse tree/some indices might be missing, use an equivalent approach with a map instead.

Solution using Java 8 stream API:

public static void main( String[] args ) {
        List<ResponseData> responseDataList = Arrays.asList(
            new ResponseData( 1, -1 ),  // changed null to -1 as null can't be a map key
            new ResponseData( 2, 1 ),
            new ResponseData( 3, 1 ),
            new ResponseData( 4, 1 ),
            new ResponseData( 5, 2 ),
            new ResponseData( 6, 2 ),
            new ResponseData( 7, 3 ),
            new ResponseData( 8, 3 ),
            new ResponseData( 9, 4 ),
            new ResponseData( 10, 4 ),
            new ResponseData( 11, 5 ),
            new ResponseData( 12, -1 ),
            new ResponseData( 13, 12 )
        );
        final Map<Integer, List<ResponseData>> map = responseDataList.stream()
                .collect( Collectors.groupingBy( o -> getLevel( responseDataList, o, 0 ) ) );
        System.out.println( map );
        // To convert the Map to a List of Lists:
        System.out.println( new ArrayList<>( map.values() ));
    }

    private static int getLevel(List<ResponseData> nodes, ResponseData responseData, int level) {
        if( responseData.parent == -1 ) {
            return level;
        } else {
            return getLevel( nodes, nodes.get( responseData.parent - 1 ), level + 1 );  // -1 to adjust index
        }
    }

    private static final class ResponseData {
        public int id;
        public int parent;

        public ResponseData( int id, int parent ) {
            this.id = id;
            this.parent = parent;
        }

        @Override
        public String toString() {
            return String.format( "{id: %d, parent: %d}", id, parent );
        }
    }

Also, this code expects that your tree is indeed a tree. Should there be any loops, it will cycle indefinitely, eventually failing with stack overflow.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=143819&siteId=1