美文网首页
将数据构建为树结构

将数据构建为树结构

作者: 帮我的鸵鸟盖个章 | 来源:发表于2018-12-27 16:46 被阅读0次

树形结构就是有层级关系的数据结构。

可以解释为:

所有数据构成一颗大树,这颗大树又是由十颗小树组成的;

这十颗小树的层级为1,并且是排序的,其pId是0,pId是自身与上一颗树的关联,0表示顶层,其值必须为唯一字段

其中每一颗小树又是由另外若干小小树组成,小小树层级为2,并且是排序的,其pId是它上一级(小树)的id

依次类推,就形成了一整颗数。

要想构建一棵树,必须有以下字段:

  • level :层级
  • sort :排序
  • pId :上一级的id
  • path :path表示为该树在一整颗数上的路径。
    • eg:A下面有B,B下面有C和D,假如path构成规则为:以id构成path,并且以/隔开,那么D的path为:/id-a/id-b/id-d/
    • path的构成规则及其重要,实际项目中需根据需求灵活使用,可以为id或者其他字段,方便查询。最后构成的path必须唯一
  • rootId :其实rootId并不是必须的,但是在实际使用中发现,加入这个字段以后,可以简化很多代码!这个字段记录的是root树的唯一标识id,在分页和查询中十分好用。

展示类似于下图

树结构.png

其中有笑gfff笑,哈哈呵呵三棵树,展开哈哈,发现有三层。

在Java中,构建一个实体类A的DTO,继承A实现轮子中的方法,增加children属性用来存放子级

构建树的轮子:

public class TreeUtils<T extends TreeUtils.Tree> {

    /**
     * 只是适用于按顺序目录结构排好序的查询方式
     *
     * @param objects  查询的全部目录(平行结构),按path降序排序
     * @param maxLevel 最大层级
     * @return
     */
    public List<T> createTree(List<T> objects, Integer maxLevel) {
        //List必须是根据codePath倒序查询得出;
        Map<Integer, List<T>> map = new HashMap<>();
        for (int i = 0; i < maxLevel; i++) {//构造层级容器
            map.put(i + 1, new ArrayList<T>());
        }
        Integer tempLevel = maxLevel + 1;//构造临时层级,为了开个头
        for (T current : objects) {
            Integer currentLv = current.getLevel();
            if (currentLv < tempLevel) {//当前层级小于临时层级
                List<T> children = map.get(currentLv + 1);//先拿子节点
                current.setChildren(children);//将子节点并入所在层级集合
                map.put(currentLv + 1, new ArrayList<T>());//然后清空子节点
            }
            map.get(currentLv).add(current);//将自己并入所在层级集合
            map.get(currentLv).sort((a, b) -> a.getSort() - b.getSort());//排序
            tempLevel = currentLv;//重新构造层级
        }
        List<T> list = map.get(1);
        return list;
    }

    /**
     * 只适用于从根节点一次清查询出来的list,不需要排好序
     *
     * @param objects
     * @return
     */
    public List<T> createTree(List<T> objects) {
        return createTree(objects, 1, "0");
    }

    /**
     * 适用于从某个节点一次清查询出来的list,不需要排好序
     *
     * @param objects
     * @return
     */
    public List<T> createTree(List<T> objects, Integer startLevel, String pid) {
        Map<Integer, Map<String, List<T>>> levelMap = new HashedMap();//保存某一级的map结构 map<三级,map<pid,子目录>>
        for (T t : objects) {
            Integer currentLevel = t.getLevel();//当前层级
            if (levelMap.get(currentLevel) == null) {
                levelMap.put(currentLevel, new HashMap<>());
            }
            if (levelMap.get(currentLevel).get(t.getpId()) == null) {
                levelMap.get(currentLevel).put(t.getpId(), new ArrayList<T>());
            }
            levelMap.get(currentLevel).get(t.getpId()).add(t);
        }
        List<T> roots = levelMap.get(startLevel).get(pid);
        roots.forEach(a -> addChildren(a, levelMap));
        roots.sort((a, b) -> a.getSort() - b.getSort());
        return roots;
    }

    void addChildren(T t, Map<Integer, Map<String, List<T>>> levelMap) {
        Map<String, List<T>> chidrenMap = levelMap.get(t.getLevel() + 1);
        if (chidrenMap != null) {
            List<T> children = chidrenMap.get(t.getId());
            if (children != null) {
                children.forEach((child) -> addChildren(child, levelMap));
                children.sort((a, b) -> a.getSort() - b.getSort());
                t.setChildren(children);
            }
        }
        return;
    }

    public interface Tree<T extends TreeUtils.Tree> {
        String getId();

        Integer getSort();

        String getpId();

        Integer getLevel();

//        String getPath();

        List<T> getChildren();

        void setChildren(List<T> childrenList);
    }

    /**
     * 只是适用于按顺序目录结构排好序的查询方式
     * 如没子集一律返回空集合
     *
     * @param objects  查询的全部目录(平行结构),按path降序排序
     * @param maxLevel 最大层级
     * @return
     */
    public List<T> createTrees(List<T> objects, Integer maxLevel) {
        //List必须是根据codePath倒序查询得出;
        Map<Integer, List<T>> map = new HashMap<>();
        for (int i = 0; i < maxLevel; i++) {//构造层级容器
            map.put(i + 1, new ArrayList<T>());
        }
        Integer tempLevel = maxLevel + 1;//构造临时层级,为了开个头
        for (T current : objects) {
            Integer currentLv = current.getLevel();
            if (currentLv < tempLevel) {//当前层级小于临时层级
                List<T> children = map.get(currentLv + 1);//先拿子节点
                if (children == null) {
                    children = new ArrayList<>();
                }
                current.setChildren(children);//将子节点并入所在层级集合
                map.put(currentLv + 1, new ArrayList<T>());//然后清空子节点
            }
            map.get(currentLv).add(current);//将自己并入所在层级集合
            map.get(currentLv).sort((a, b) -> a.getSort() - b.getSort());//排序
            tempLevel = currentLv;//重新构造层级
        }
        List<T> list = map.get(1);
        return list;
    }


}

实体类:

public class EpcSystemDictionary extends SuperEntity{
    private String id;
    private Date createTime;
    private Date updateTime;
    private String code; //编号
    private String name; //名称
    private Integer sort;//排序
    private String pId;//父id
    private String enName;
    private Integer isDelete;
    private Integer level;//层级
    private String path;

    public EpcSystemDictionary() {
    }

    public EpcSystemDictionary(String id, String code, String name,String enName, Integer sort, String pId, Integer level, String path) {
        this.id = id;
        this.code = code;
        this.name = name;
        this.enName=enName;
        this.sort = sort;
        this.pId = pId;
        this.level = level;
        this.path = path;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getSort() {
        return sort;
    }

    public void setSort(Integer sort) {
        this.sort = sort;
    }

    public String getpId() {
        return pId;
    }

    public void setpId(String pId) {
        this.pId = pId;
    }

    public String getEnName() {
        return enName;
    }

    public void setEnName(String enName) {
        this.enName = enName;
    }

    public Integer getIsDelete() {
        return isDelete;
    }

    public void setIsDelete(Integer isDelete) {
        this.isDelete = isDelete;
    }

    public Integer getLevel() {
        return level;
    }

    public void setLevel(Integer level) {
        this.level = level;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }
}

DTO:

public class EpcSystemDictionaryDto extends EpcSystemDictionary implements TreeUtils.Tree<EpcSystemDictionaryDto> {

    List<EpcSystemDictionaryDto> children = new ArrayList<>();

    @Override
    public List<EpcSystemDictionaryDto> getChildren() {
        return children;
    }

    @Override
    public void setChildren(List<EpcSystemDictionaryDto> childrenList) {
        this.children=childrenList;
    }

}

调用:

/**
     * 获取字典某一个根列表
     *
     * @param
     * @return
     */
    @Override
    public EpcSystemDictionaryDto getOneRoot(String name, Long companyId) {
        //避免写接口地址的时候传入的name后面没有写“/”
        name = name.length() == (name.lastIndexOf("/") + 1) ? name : name + "/";
        List<EpcSystemDictionaryDto> epcSystemDictionaryList = epcSystemDictionaryMapper.selectOneRoot(name, companyId);
        for (EpcSystemDictionaryDto e : epcSystemDictionaryList) {
            if (e.getPath().equals(name)) {
                return new TreeUtils<EpcSystemDictionaryDto>().createTree(epcSystemDictionaryList, e.getLevel(), e.getpId()).get(0);
            }
        }
        return new EpcSystemDictionaryDto();
    }

代码其实不难,难的是操作数据的思想,对数据结构变化的把握,通过数据的现时情况得到自己想要的结果。

路漫漫其修远兮,吾将上下而求索。

相关文章

  • 将数据构建为树结构

    树形结构就是有层级关系的数据结构。 可以解释为: 所有数据构成一颗大树,这颗大树又是由十颗小树组成的; 这十颗小树...

  • 6-玩转数据结构-二分搜索树

    之前我们的课程都在关注线性的数据结构,我们从本章开始学习树结构,二分搜索树。 树结构: 线性数据结构是将数据排成一...

  • 构建一个Node树

    方便遍历查找数据,比如存储机构人员数据。 建立 Node 对象 将集合建立成树结构

  • 03-树结构

    树结构依靠节点、叶子节点、子树将自身的数据扩展为像一棵倒过来的树 1. 什么是树结构 树结构依托路径、节点、叶子节...

  • 树结构,将同级的member,push到children中

    期望 将member中的数据当成chilren来遍历,为了适应于element的树结构组件 初始数据结构

  • 详谈树结构(传统树、字典树、hash 树、Merkle Patr

    关于数据结构中树结构的相关分享 本文参考: 树结构参考文献 一、传统的数据结构中的树结构 树结构是一种非线性存储结...

  • 我的开源-自定义树形结构-YPTreeView

    树形结构视图,数据源无顺序要求,自动构建树结构。 支持多选单选,支持改各种颜色。 使用示例: - (void)vi...

  • 数据结构与算法基础

    数据结构部分,需要重点关注链表、树结构和图结构(邻接矩阵)。包括各个结构的构建、操作、优化,以及各个结构在不同场景...

  • 树结构打平为一维数组

    树组件通用知识点:树结构打平为一维数组给定如下数据结构:

  • element ui 树结构

    这是一个封装好的树结构 接下来是子组件写法: 其中,构建树的数据如下: 控制台输出的所勾选的数据,获取的内容 通过...

网友评论

      本文标题:将数据构建为树结构

      本文链接:https://www.haomeiwen.com/subject/qlcdlqtx.html