• 树形结构


    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;
        }
    }
  • 相关阅读:
    jichu
    scanf
    数位dp
    hdu 5667
    华东交通大学2018年ACM“双基”程序设计竞赛 K
    华东交通大学2018年ACM“双基”程序设计竞赛 D
    map
    次小生成树
    set
    c++11之为什么C++11引入了std::ref?
  • 原文地址:https://www.cnblogs.com/zzq-include/p/12450401.html
Copyright © 2020-2023  润新知