如何将类别的集合转换为树结构

时间:2018-12-13 07:06:25

标签: java tree

我正在使用p:multiSelectListbox做树选择器。我有类别的集合,并且尝试将类别转换为组件支持的结构(类别是无序的)。 这是我的类别bean:

public class Category {
    private String id;
    private String pid; //parentId
    private String name;
    private String value;

    //getter and setter
}

这是我的转换方法:

public List<SelectItem> tree(List<Category> categories) {
    Map<Category, SelectItem> map = new HashMap<>();

    for (Category node : categories) {
        //Check if current category is leaf node, if true new SelectItem, else new SelectItemGroup
        SelectItem item;
        if (categories.stream().noneMatch(n -> node.getId().equals(n.getPid()))) {
            item = new SelectItem(node.getValue(), node.getName());
        } else {
            item = new SelectItemGroup(node.getName());
        }
        map.put(node, item);
    }
    //the result return
    //items just add the root level, and child level add into it's parent level
    List<SelectItem> items = new ArrayList<>();

    categories.forEach(node -> {
        //get parent category of current's
        SelectItem item = map.get(categories.stream().filter(n -> n.getId().equals(node.getPid())).findFirst().orElse(null));

        //parent category is not exists, it's mean current category is root level
        if (item == null) {
            items.add(map.get(node)); //add root
        } else {
            SelectItemGroup parentGroup = (SelectItemGroup) item;
            SelectItem[] selectItems = parentGroup.getSelectItems();

            List<SelectItem> selectItemList = new ArrayList<>();
            if (selectItems != null) selectItemList.addAll(Arrays.asList(selectItems));
            //add current category into it's parent's children
            selectItemList.add(map.get(node));
            parentGroup.setSelectItems(selectItemList.toArray(new SelectItem[0]));
        }
    });

    return items;
}

当类别的大小小于10000时,他表现很好;如果大小大于20000,它将变得非常慢。有谁知道更有效的方法?

1 个答案:

答案 0 :(得分:2)

这些代码的时间复杂度为O(n ^ 2):

categories.forEach(node -> { //get parent category of current's SelectItem item = map.get(categories.stream().filter(n -> n.getId().equals(node.getPid())).findFirst().orElse(null))

根据pid&id关系,从类别列表中制作树结构可以使用HashMap以O(n)时间复杂度完成。下面介绍了一些基本概念。

  1. 遍历类别列表,并将pid&id映射放入HashMap,时间复杂度:O(n)。在地图中,我们将(pid:List of children ids)作为Map.Entity。现在我们实际上已经有了树结构。

  2. 我们下一步要做的是遍历通过哈希图演示的树,并获得结果。这可以通过@Ken Bekov给出的递归方式来完成,也可以使用迭代方式来完成。穿刺程序也需要O(n)时间。

因此,整个解决方案的时间复杂度为O(n)。如果n为lagre,例如说20000,它应该比原始解决方案快得多。