简体   繁体   English

Java使用平面文件中的父ID创建多个类似树的结构

[英]java create multiple tree like structure using parent id from flat file

I have data like below 我有如下数据

CategoryId  CategoryName  CategoryParentId
123         XYZ           111
111         ABC           
222         PQR           
555         DEF           111
321         IJK           222

If you see this a unordered data read from a flat file which can be in any order. 如果您看到此消息,则从平面文件读取的无序数据可以是任何顺序。

I want to create trees like below: 我想创建如下树:

111
|  \
123 555  

and

222
\
321

I have this data in an object, which looks like below: 我在一个对象中有此数据,如下所示:

public class Category {
    private String id = null;
    private String name = null;
    private String parentId = null;

    public Category(String id, String name, String parentId) {
        this.id = id;
        this.name = name;
        this.parentId = parentId;
    }
}

I am trying to process this data to create list of categories tree. 我正在尝试处理此数据以创建类别树列表。

public class CategoryTree {
    private String name     = null;
    private String id       = null;

    private CategoryTree<String, CategoryTree> children = new TreeMap<String, CategoryTree>();


    public CategoryTree() {
    }

    public CategoryTree(String name, String id) {
        setName(name);
        setId(id);
    }

    public TreeMap<String, CategoryTree> getChildren() {
        return this.children;
    }

    public CategoryTree getChild(String childId) {
        return this.children.get(childId);
    }

    public void setChild(CategoryTree child) {
        this.children.put(child.getId(), child);
    }

    public boolean hasChild(String childId) {
        TreeMap<String, CategoryTree> set = this.children;
        boolean result =  set.containsKey(childId);
        return result;
    }
}

Below is what I am trying to do: 以下是我要执行的操作:

public void processData(List categoryList) {
    List<CategoryTree> roleObjectList = new ArrayList<CategoryTree>();

    Iterator<Category> itr = categoryList.iterator();
    while (itr.hasNext()) {
        Category entry = itr.next();
        String id = entry.getId();
        String name = entry.getName();
        String parentId = entry.getParentId();

        // i am confused here
        // CategoryTree parent = new CategoryTree(name,  id);
           parent.addChild(entry);
    }
}

I am confused on this part. 我对此感到困惑。 How to start the tree. 如何启动树。 Since entry in the first iteration of loop has parent but it's parent is not present in the final list yet. 由于循环的第一次迭代中的条目具有父级,但最终列表中还没有父级。 How to add first entry to it's parent. 如何将第一项添加到其父项。

You can build your tree recursively. 您可以递归地构建树。 First step will be to extract the roots of your trees. 第一步将是提取树木的根。 Then create a function who get the direct children of each node by running on the list ( O(n) ) - inside there will be recursive call for each of the children. 然后创建一个函数,该函数通过在列表( O(n) )上运行来获取每个节点的直接子代-内部将为每个子代递归调用。

I guess my JAVA syntax is little but rusty so this is the pseudo code: 我猜我的JAVA语法很少但很生锈,所以这是伪代码:

function getChildren(nodeID, listOfNodes):
    childrenList = empty list 
    for each node in listOfNodes:
        if node.parentId == nodeID: // if node is direct child
            node.children = getChildren(node.id, listOfNodes); //recursively get all his children 
            childrenList.add(node) // add it to the children list
    return childrenList;

main:
     listOfNodes = get list from your file
     listOfRoots = init empty list
     for each node in listOfNodes:
         if (node.parentId is empty) //not parent
             listOfRoots.add(node)
     // now listOfRoots is has all the roots
     for each node in listOfRoots:
         node.children = getChildren(node.id, listOfNodes)

This will be in O(n^2) complexity. 这将是O(n^2)复杂度。 2 immediate improvement you can do is save the listOfNode in object and used it as this so you won't need to overload the memory. 2立即改善你能做的就是保存在对象中的listOfNode,并用它作为this ,所以你不会需要重载内存。 Second, you can modify the list each time and remove the node that assign (as he cannot be assign twice...) 其次,您可以每次修改列表并删除分配的节点(因为不能两次分配他...)

Hope that helps! 希望有帮助!

It seems that the parent.id < child.id holds, that is: the parent is created first. 似乎parent.id < child.id成立,即:首先创建了父级。 Though not necessary, that condition could sometimes ease things. 尽管不是必需的,但这种情况有时可以缓解问题。

Here it is not needed. 在这里不需要。

public void processData(List<Category> categoryList) {
    Map<String, CategoryTree> map = categoryList.collect(
            Collectors.toMap(cat -> cat.id,
                             cat -> new CategoryTree(id, name)));
    List<CategoryTree> treeRoots = new ArrayList<>(); // Forrest if more than one root.
    categoryList.forEach(cat -> {
        CategoryTree node = map.get(cat.id);
        if (cat.parentId != null) {
            CategoryTree parent = map.get(cat.parentId)
            parent.children.add(node );
        } else {
            treeRoots.add(node );
        }
    });
    List<CategoryTree> roleObjectList = new ArrayList<>(map.values());
    ...

Though maybe faster than a path following algorithm (that could exploit the id order), it needs additional memory: an extra map. 尽管可能比遵循路径算法(可以利用id顺序)更快,但它需要额外的内存:额外的映射。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM