业务实战中用到树结构

2023-06-30 10:47:46 浏览数 (2)

一.简介

最近业务中个场景,行业分级,用到树结构,抽象出一些普通树的场景。

二.示例

代码语言:javascript复制
import lombok.Data;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;

/**
 * @Classname Tree
 * @Description TODO
 * @Date 2020/2/17 4:06
 * @Created by limeng
 */
@Data
public class Tree<T> extends HashMap<String,Object> {
    private static final String CHILDREN_T = "children";

    private static final String ID_T = "id";

    private static final String PARENT_ID = "parentId";

    private static final String TREE_LEVEL_T = "treeLevel";


    public void setChildren(List<Tree<T>> children){
        this.put(CHILDREN_T, children);
    }

    public List<Tree<T>> getChildren(){
        return (List<Tree<T>>) this.get(CHILDREN_T);
    }

    public void setId(String id){
        this.put(ID_T, id);
    }

    public String getId(){
        return (String) this.get(ID_T);
    }

    public void setParentId(String parentId){
        this.put(PARENT_ID, parentId);
    }

    public String getParentId(){
        return (String) this.get(PARENT_ID);
    }
    public Tree(){}



    /***
     * 获取节点父子属性对象
     * @param node
     * @return
     * @throws Exception
     */
    public void setNodeAttr(T node){
        Class nodeClass = node.getClass();
        try{
            Field treeIdField = nodeClass.getDeclaredField("id");
            treeIdField.setAccessible(true);
            this.setId((String) treeIdField.get(node));
            this.setNode(node);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public void setNode(T node){
        Class c = node.getClass();
        Field[] fields = c.getDeclaredFields();
        for(Field field : fields){
            String name = field.getName();
            try{
                field.setAccessible(true);
                this.put(name, field.get(node));
            }catch(IllegalAccessException e){
                e.printStackTrace();
            }
        }
    }
}
代码语言:javascript复制
import lombok.Data;

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

/**
 * @Classname TreeVO
 * @Description TODO
 * @Date 2020/2/17 4:14
 * @Created by limeng
 */
@Data
public class TreeVO<T> {
    /***
     * 树的深度
     */
    private Integer depth;

    /***
     * 节点数量
     */
    private Integer NumberOfNodes;

    /***
     * 普通树森林集合
     */
    private List<Tree<T>> treeList;


    public void setTreeList(List<Tree<T>> list){
        Map<String,Tree<T>> idMap=new HashMap<>();
        this.setNodeMap(list,idMap);
        if(this.treeList == null){
            this.treeList =new ArrayList<>();
        }
        for(Tree<T> tree:list){
            String parentId = tree.getParentId();
            Tree<T> parentNode = idMap.get(parentId);
            //如果找不到此节点的父节点的的话说明此节点为根节点
            if(parentNode == null){
                this.treeList.add(tree);
            }else{
                //如果不为空,则说明此节点为当前列表中存在父节点,则将此节点插入
                List<Tree<T>> children = parentNode.getChildren();
                if(children == null){
                    children = new ArrayList<>();
                    children.add(tree);
                    parentNode.setChildren(children);
                }else{
                    parentNode.getChildren().add(tree);
                }

            }

        }


    }



    private void setNodeMap(
            List<Tree<T>> list,
            Map<String, Tree<T>> idMap
    ){
        for(Tree<T> tree : list){
            if(tree.getChildren() == null){
                tree.setChildren(new ArrayList<Tree<T>>());
            }
            idMap.put(tree.getId(), tree);
        }
    }

    private void setParentIdMap(
            List<TreeNodeAttrDTO<T>> list,
            Map<Integer, Tree<T>> parentIdMap
    ){
    }

}
代码语言:javascript复制
import com.knowlegene.core.model.BaseIncrementIdModel;

import java.util.Date;

/**
 * 电路树
 * @Classname ElectricTree
 * @Description TODO
 * @Date 2020/3/2 11:16
 * @Created by limeng
 */
public class ElectricTree extends BaseIncrementIdModel {
    private String label;
    private String parentId;
    private String description;
    private Integer sort;
    private Date createDate;
    private Date updateDate;
    private String nodeType;

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    public String getParentId() {
        return parentId;
    }

    public void setParentId(String parentId) {
        this.parentId = parentId;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Integer getSort() {
        return sort;
    }

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

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    public Date getUpdateDate() {
        return updateDate;
    }

    public void setUpdateDate(Date updateDate) {
        this.updateDate = updateDate;
    }

    public String getNodeType() {
        return nodeType;
    }

    public void setNodeType(String nodeType) {
        this.nodeType = nodeType;
    }
}

上述是树抽象类构建和实体,下面一些查询,组建树的过程。

代码语言:javascript复制
   /**
     * 查询所有子节点
     *
     * @param id
     * @return
     */
    @Override
    public List<Tree<ElectricTreeDTO>> queryByAllChildList(String id,int levelVal) {
        List<Tree<ElectricTreeDTO>> treeList=new ArrayList<>();
        int level = 0;
        treeList = this.queryByChildList(id,level,levelVal,treeList);

        ElectricTree electricTree = this.queryByElectricTreeId(id);
        if(electricTree != null){
            ElectricTreeDTO electricTreeDTO = new ElectricTreeDTO();
            BeanUtil.copyBean(electricTree,electricTreeDTO);
            Tree<ElectricTreeDTO> tree =new Tree<>();
            tree.setId(id);
            tree.setParentId(electricTree.getParentId());
            tree.setNode(electricTreeDTO);
            treeList.add(tree);
        }

        return treeList;
    }

    /**
     * 查询多级
     * @param id
     * @param level
     * @return
     */
    private List<Tree<ElectricTreeDTO>> queryByChildList(String id, int level,int levelVal,List<Tree<ElectricTreeDTO>> treeList) {
        if(level < levelVal && StringUtil.isNotBlank(id)){

            ElectricTreeDTO electricTreeDTO = null;
            Tree<ElectricTreeDTO> tree =null;

            List<Condition> conditionList = new ArrayList<>();
            conditionList.add(Condition.parseCondition("parentId_eq").setValue(id));
            List<ElectricTree> electricTrees = electricTreeBiz.find(conditionList);
            if(!CollectionUtil.isEmpty(electricTrees)){
                String id2 = null;
                for(ElectricTree electricTree:electricTrees){
                     id2 = electricTree.getId();
                     if(StringUtil.isEmpty(id2)) continue;

                     tree = new Tree<>();
                     electricTreeDTO = new ElectricTreeDTO();
                     BeanUtil.copyBean(electricTree,electricTreeDTO);
                     tree.setId(id2);
                     tree.setNode(electricTreeDTO);
                     tree.setParentId(electricTree.getParentId());
                     treeList.add(tree);

                     treeList = this.queryByChildList(id2,level 1,levelVal,treeList);
                }
            }

        }
        return treeList;
    }

/**
* 组建树
* treeVO = new TreeVO<>();
* treeVO.setTreeList(treeList);
*
**/

上述通过递归查询,可以控制查询到多少层。

0 人点赞