需要根据父子关系将数据列表转换为嵌套列表。

4
我可以帮您进行翻译。以下是您需要翻译的内容:

我需要根据父子关系将数据列表转换为列表。如果父级为空,则降到一级,二级将基于一级 id。

我的数据如下所示:

[
    {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 },
]

我的代码是:

响应数据

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);
    }
}

上述地图将包含父项作为键和映射到父项的值的地图。
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);
}

我的输出结果如下:
[
    [ {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 }]
]

但是我期望的输出应该像下面这样:

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 }]
]

请查看并告诉我我们如何实现相同的内容。先行致谢。

为什么不将这个转换为流,并使用“Collectors.groupingBy(parent#getId,Collection#List)”来保持简单呢?这将提供良好的可读性,同时在UI中表示Key,Pair值的干净JSON(只是建议)。 - bananas
好的。一旦我的逻辑被修复并且开始按照我的期望工作,我将把代码转换为流。感谢您的建议@emotionlessbananas。 - Abdul
1个回答

3

为了表示树形结构,我使用了一个 ArrayList,其中节点的索引等于它在数组中的索引加 1。如果你有一个稀疏的树/一些索引可能会丢失,可以使用一个映射等效的方法。

使用 Java 8 流 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 );
        }
    }

此代码也期望您的树确实是一棵树。如果有任何循环,它将无限循环,最终导致堆栈溢出。

1
你可以使用 new ArrayList<>( map.values() ) 将 Map 转换为列表的列表。 - Ondra K.
我看到你正在将父元素2、3和4分组在一起。怎么做的?规则是什么?您可以通过传递所需的lambda函数,在Collectors#groupingBy方法中编写自己的逻辑。 - Ondra K.
我需要根据级别维护列表。当前级别列表是前一级别的子级。我们可以通过父级找到它们。第一级默认为-1,下一级基于父级。因此,第一级包含对象ID 1,下一级将是所有包含父级1的对象,以此类推。第三级对象的父级存在于第二级中。@OndraK - Abdul
@Abdul 最佳解决方案是使用流。所以上面的答案是正确的。如果你对 NodeJS 中这些分组是如何实现的感兴趣,请查看以下软件包 https://www.npmjs.com/package/group-array - Alexpandiyan Chokkan
1
我正在尝试为您添加赏金,但出现错误提示称我必须在6小时后才能授予赏金。我会在6小时后为您提供赏金。@OndraK。 - Abdul
显示剩余17条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接