树形结构

package com.viewhigh.bi.service.helper;

import com.viewhigh.bi.common.utils.BasicUtils;
import com.viewhigh.bi.common.utils.ObjectUtil;
import com.viewhigh.bi.model.business.category.Tree;
import com.viewhigh.bi.model.metadata.Category;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by zzq on 2017/7/28.
 */
@Component
public class CategoryConversion {
    /**
     * 构建树形结构时,取出不同模块的节点
     *
     * @param modelName
     * @return
     */
    public static PropMapper buildPropMapper(final String modelName) {
        return new CategoryConversion.PropMapper<Map<String, String>>() {
            @Override
            public String getId(Map<String, String> item) {
                return item.get(modelName + "$id");
            }

            @Override
            public String getName(Map<String, String> item) {
                return item.get(modelName + "$name");
            }

            @Override
            public String getCode(Map<String, String> item) {
                return item.get(modelName + "$code");
            }

            @Override
            public String getCategoryId(Map<String, String> item) {
                return item.get(modelName + "$category_id");//chart_model
            }
        };
    }

    /**
     * @param categoryList 仅仅是主题分类和实际模型的所属关系集合,包括分类信息,并不包括具体数据信息
     * @param modelDetail  如分析模型,图表模型等能够属于主题分类的详细内容,加到对应的树节点当中
     * @param categoryRoot 带有parent_id平铺分类的根节点
     * @param treeRoot     转成树结构的根节点
     * @param treeRootList 当执行该方法时在treeRootList中包含treeRoot
     * @param title        按照名称过滤
     * @return
     */
    public Tree categoryAndModel2Tree(List<Category> categoryList, Map<String, Object> modelDetail, Category categoryRoot, Tree treeRoot, List<Tree> treeRootList, String title) {
        if (categoryList == null || categoryList.size() == 0 || categoryRoot == null)
            return treeRoot;

        Category category;
        Object modelMap;
        List<Category> treeListChildrenTmp;
        List<Tree> treeArrayList;

        for (int i = 0; i < categoryList.size(); i++) {
            category = categoryList.get(i);
            if (category.getParent_id().equals(categoryRoot.getId())) {
                Tree tree = new Tree();
                tree.setScore(category.getOrder_num());
                tree.setDesc(category.getRemark());
                String name = category.getName();
                 if (StringUtils.isNotBlank(title) &&
                        (name.toLowerCase().contains(title.toLowerCase()) || treeRootListIncludeTitle(treeRootList, title))
                        ) {//如果当前子节点被过滤出来则父节点也需要保留
                    for (Tree item : treeRootList)
                        item.setFilter(true);
                    tree.setFilter(true);
                }
                tree.setTitle(category.getName());
                String modelId = category.getId();
                tree.setKey(modelId);

                if (!category.isCategory() && modelDetail != null && modelDetail.containsKey(modelId)) {
                    modelMap = modelDetail.get(modelId);
                    tree.setDetail(modelMap);
                }

                if (categoryRoot.getChildren() == null) {
                    treeListChildrenTmp = new ArrayList();
                    treeListChildrenTmp.add(category);
                    categoryRoot.setChildren(treeListChildrenTmp);

                    treeArrayList = new ArrayList();
                    treeArrayList.add(tree);
                    treeRoot.setChildren(treeArrayList);
                } else {
                    categoryRoot.getChildren().add(category);
                    treeRoot.getChildren().add(tree);
                }

                categoryList.remove(i);
                i--;//删除已经确定节点的元素,减少时间复杂度
            }
        }

        List<Category> categoryListChildren = categoryRoot.getChildren();

        if (categoryListChildren == null)
            return treeRoot;

        List<Tree> treeListChildren = treeRoot.getChildren();

        if (treeListChildren == null)
            return treeRoot;

        for (int i = 0; i < categoryListChildren.size(); i++) {
            Tree currTree = treeListChildren.get(i);
            List<Tree> treeRootListNew = null;
            if (StringUtils.isNotBlank(title)) {
                treeRootListNew = new ArrayList<>();//如果不为子节点的话,将所有父级存储并记录,如果子节点为保留状态所有父节点均设置为保留状态
                for (Tree item : treeRootList)
                    treeRootListNew.add(item);
                treeRootListNew.add(currTree);
            }
            categoryAndModel2Tree(categoryList, modelDetail, categoryListChildren.get(i), currTree, treeRootListNew, title);
        }

        return treeRoot;
    }
private boolean treeRootListIncludeTitle(List<Tree> treeRootList, String title) {
        for (Tree item : treeRootList) {
            String name = item.getTitle();
            if (name.contains(title)) {
                return true;
            }
        }
        return false;
    }
    public <Bean> Tree build(List<Category> categoryList, List<Bean> modelData, PropMapper<Bean> propMapper) {
        return build(categoryList, modelData, propMapper, null);
    }

    /**
     * 根据分类元数据,生成分类树的结构
     *
     * @param categoryList
     * @param modelData
     * @param propMapper
     * @param title        用来进行对title的模糊匹配
     * @param <Bean>
     * @return
     */
    public <Bean> Tree build(List<Category> categoryList, List<Bean> modelData, PropMapper<Bean> propMapper, String title) {
        if (categoryList == null || categoryList.size() == 0)
            return null;

        //深copy对象categoryList不改变原有对象,防止多线程使用冲突
        List<Category> categoryListCopy = ObjectUtil.deepCopy(categoryList);

        //0.找到根元素,并从完整集合中删除,减少没有必要的遍历
        Category categoryRoot = null;//treeList.remove(0);

        int indexRoot = 0;
        for (int i = categoryListCopy.size() - 1; i > -1; i--) {
            categoryRoot = categoryListCopy.get(i);
            indexRoot = i;
            if (StringUtils.isBlank(categoryRoot.getParent_id()))
                break;
        }
        categoryListCopy.remove(indexRoot);

        //1.构建根级别的树节点用于返回,子节点直接在其中累加
        Tree treeRoot = new Tree();
        treeRoot.setScore(categoryRoot.getOrder_num());
        treeRoot.setKey(categoryRoot.getId());
        String name = categoryRoot.getName();
        treeRoot.setFilter(true);//根节点始终保留
        treeRoot.setTitle(name);
        treeRoot.setDesc(categoryRoot.getRemark());

        Map<String, Object> modelDataMap = null;

        if (propMapper != null && modelData != null) {
            //2.将具体模型的list转换成map,用于将模型具体信息递归添加到树对应的位置
            modelDataMap = new HashMap();

            Category categoryTmp;

            for (Bean item : modelData) {//一次遍历将list转换为带有id的map
                modelDataMap.put(propMapper.getId(item), item);

                //3.将具体模型信息与分类信息合并
                categoryTmp = new Category();
                categoryTmp.setId(propMapper.getId(item));
                categoryTmp.setName(propMapper.getName(item));
                categoryTmp.setCode(propMapper.getCode(item));
                categoryTmp.setParent_id(propMapper.getCategoryId(item));
                categoryTmp.setCategory(false);//标志不是非分类信息实体,仅仅将属性映射成该类型
                categoryListCopy.add(categoryTmp);
            }
        }

        List<Tree> treeRootList = null;
        if (StringUtils.isNotBlank(title)) {
            treeRootList = new ArrayList<>();
            treeRootList.add(treeRoot);
        }
        Tree result = categoryAndModel2Tree(categoryListCopy, modelDataMap, categoryRoot, treeRoot, treeRootList, title);
        if (StringUtils.isNotBlank(title)) {
            if (!result.isFilter())
                return null;
            result = filterTreeNode(result);
        }
        return result;
    }

    private Tree filterTreeNode(Tree result) {
        List<Tree> treeList = result.getChildren();
        if (BasicUtils.isEmpty(treeList))
            return null;
        for (int i = 0; i < treeList.size(); i++) {
            Tree currTree = treeList.get(i);
            if (currTree.isFilter()) {
                filterTreeNode(currTree);
            } else {
                treeList.remove(i);
                i--;
            }
        }
        return result;
    }

    public interface PropMapper<Bean> {
        String getId(Bean item);

        String getName(Bean item);

        String getCode(Bean item);

        String getCategoryId(Bean item);
    }
}
package com.viewhigh.bi.model.metadata;

import java.util.List;

/**
 * Created by zzq on 2017/6/28.
 */
public class Category extends BasicModelMetaData {
    private String parent_id;
    private List<Category> children;
    //用于判断是否为分类主题标识,模型合并时用该属性做区分
    private boolean isCategory = true;
    private String order_num;

    public String getOrder_num() {
        return order_num;
    }

    public void setOrder_num(String order_num) {
        this.order_num = order_num;
    }

    public boolean isCategory() {
        return isCategory;
    }

    public void setCategory(boolean category) {
        isCategory = category;
    }

    public List<Category> getChildren() {
        return children;
    }

    public void setChildren(List<Category> children) {
        this.children = children;
    }

    public String getParent_id() {
        return parent_id;
    }

    public void setParent_id(String parent_id) {
        this.parent_id = parent_id;
    }
}
package com.viewhigh.bi.model.business.category;

import java.io.Serializable;
import java.util.List;

/**
 * Created by zzq on 2017/7/27.
 */
public class Tree implements Serializable {
    private String key;
    private String title;
    private String desc;
    private Object detail;//没有
    private List<Tree> children;
    private String score;
    private boolean filter = false;

    public boolean isFilter() {
        return filter;
    }

    public void setFilter(boolean filter) {
        this.filter = filter;
    }

    public String getScore() {
        return score;
    }

    public void setScore(String score) {
        this.score = score;
    }

    public List<Tree> getChildren() {
        return children;
    }

    public void setChildren(List<Tree> children) {
        this.children = children;
    }

    public Object getDetail() {
        return detail;
    }

    public void setDetail(Object detail) {
        this.detail = detail;
    }

    public Tree() {

    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}
原文地址:https://www.cnblogs.com/zzq-include/p/12450401.html