从Java Hashmap生成树结构

时间:2019-03-22 18:53:47

标签: java json tree hashmap parent-child

我目前有一个带有几个属性的类,这些属性描述了系统中某种类型的对象。此类称为EnrollmentInfo

我还有一个哈希表,其结构如下;

HashMap<EnrolmentInfo, List<EnrolmentInfo>> devices = new HashMap<>();

可以看出,此哈希图中的value属性包含EnrollmentInfo类类型的ArrayList。 为了提供一些上下文,此哈希图用于将树结构的父节点和关联的子节点保存为键,值对。

我通过遍历子表/父表并从中提取细节来生成此哈希图,如下所示:

Child : Parent
    1 : 0
    2 : 0
    3 : 2
    4 : 0
    5 : 4
    6 : 4
    7 : 1
    8 : 6

提取父母和孩子并将其放入HashMap的代码如下:

        // Extracts the parents and assigns them to the key values
        for (EnrolmentInfo enrolmentInfo : enrolmentInfos) {
            Integer nodeParentId = enrolmentInfo.getParentId();
            EnrolmentInfo parentEnrolmentInfo = dms.getDevice(nodeParentId).getEnrolmentInfo();
            devices.put(parentEnrolmentInfo, new ArrayList<EnrolmentInfo>());
        }
        // Extracts the children and assigns them to the children arraylist of each associated parent.
        for (EnrolmentInfo enrolmentInfo : enrolmentInfos) {
            int nodeId = enrolmentInfo.getId();
            Integer parentId = enrolmentInfo.getParentId();
            EnrolmentInfo nodeEnrolmentInfo = dms.getDevice(nodeId).getEnrolmentInfo();
            for (Map.Entry<EnrolmentInfo, List<EnrolmentInfo>> parentDevice : devices.entrySet()) {
                if (parentDevice.getKey().getId() == parentId) {
                    parentDevice.getValue().add(nodeEnrolmentInfo);
                    break;
                }
            }
        }

我现在的问题是将该哈希图组成一个实际的树形结构,以便可以通过JSON库将其编译为人类可读的形式。

更具体地说,如何根据上述HashMap生成嵌套树结构?

编辑: 下面显示的是我最后期望的一种JSON格式的示例结构。

{
    "id" : 0,
    "children" : [
        {
            "id" : 1,
            "children" : [
                {
                    "id" : 7,
                    "children" : []
                }
            ]
        },
        {
            "id" : 2,
            "children" : [
                {
                    "id" : 3,
                    "children" : []
                }
            ]
        },
        {
            "id" : 4,
            "children" : [
                {
                    "id" : 5,
                    "children" : []
                },
                {
                    "id" : 6,
                    "children" : [
                        {
                            "id" : 8,
                            "children" : []
                        }
                    ]
                }
            ]
        }
    ]
}

编辑: 到目前为止,我已经创建了一个如下所示的Bean类:

public class DeviceHierarchyNode implements Serializable {
@ApiModelProperty(name = "id", value = "ID of the node generated. Same as Device ID",
        required = true)
private int id;

@ApiModelProperty(name = "label", value = "Device name as suggested by the user.",
        required = true)
private String label;

@ApiModelProperty(name = "children", value = "List of child devices associated with device if any",
        required = true)
private List<DeviceHierarchyNode> children;

我的计划是使用它来创建最终的嵌套结构。

1 个答案:

答案 0 :(得分:1)

警告:hacky。

您能否创建一个包裹基础的节点类型:

public class EnrolmentInfoNode {
    private EnrolmentInfo info;
    private List<EnrolmentInfoNode> children;

    public EnrolmentInfoNode(EnrolmentInfo contents) {
        this.info = contents;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + info.getId();
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        EnrolmentInfoNode other = (EnrolmentInfoNode) obj;
        if (info.getId() != other.info.getId())
            return false;
        return true;
    }

    public void addChild(EnrolmentInfoNode child) {
        if (children == null) {
            children = new ArrayList<>();
        }

        children.add(child);
    }
}

然后重新映射:

    Map<EnrolmentInfo, EnrolmentInfoNode> nodeMap = new HashMap<>();

    for (Entry<EnrolmentInfo, List<EnrolmentInfo>> entry : map.entrySet()) {
        for (EnrolmentInfo child : entry.getValue()) {
            EnrolmentInfoNode childNode = nodeMap.computeIfAbsent(child, EnrolmentInfoNode::new);

            nodeMap.computeIfAbsent(entry.getKey(), EnrolmentInfoNode::new)
                   .addChild(childNode);
        }
    }

假设您知道节点0是父节点:

    String json = new GsonBuilder().setPrettyPrinting()
                                   .create()
                                   .toJson(nodeMap.get(enrolmentInfo0));

    System.out.println(json);

如果不这样做,则可以向EnrolmentInfoNode添加一个“ parentNode”字段,然后扫描节点映射以查找第一个具有空父级(因此为root)的节点,然后去比赛。