递归创建树形结构数据

递归创建树形结构数据
创建一个树形结构对象,然后用递归算法,返回前端一个树形的list集合
1、先创建实体对象,树形结构必须要有关联的pid字段

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Node implements IBaseTree{

    /**
     * 主键id
     */
    private Integer id;

    /**
     * 名称
     */
    private String name;

    /**
     * 关联父id
     */
    private Integer pid;

    /**
     * 关联子对象集合
     */
    private List<Node> children = new ArrayList<>();


    public Node(Integer id,String name,Integer pid){
        this.id = id;
        this.name = name;
        this.pid = pid;
    }
}

2、下面是转换数据的工具类:直接使用的是递归算法

public class TreeUtil {
	/**
     * 建树
     * @param list
     * @return
     */
    public static List<Node> build(List<Node> list){
        List<Node> res = new ArrayList<>();
        for (Node node : list) {
            //如果是父节点,就查找下面所有字节点添加到子节点的集合中,也可以先把所有一级节点过滤出来遍历
            if(node.getPid()==0){
                buildChildren(node,list);
                res.add(node);
            }
        }
        return res;
    }

    /**
     *  递归查找一个节点下的所有子节点
     * @param node
     * @param list
     */
    public static void buildChildren(Node node,List<Node> list){
        //将所有的一级子节点查询出来
        List<Node> children = list.stream().filter(p->p.getPid().equals(node.getId())).collect(Collectors.toList());
        //如果一级子节点不为空,开始递归查找所有节点,直到子节点集合为空停止
        if(!CollectionUtils.isEmpty(children)){
            for (Node n : children) {
                buildChildren(n,list);
            }
            node.setChildren(children);
        }
    }
}

下面是单元测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class ServiceControllerTest {
	@Test
    public void test01() throws Exception {
    	List<Node> nodes = new ArrayList<>();
        nodes.add(new Node(1,"湖北",0));
        nodes.add(new Node(2,"湖南",0));
        nodes.add(new Node(3,"武汉",1));
        nodes.add(new Node(4,"武昌区",3));
        nodes.add(new Node(5,"黄冈",1));
        List<Node> list = TreeUtil.build(nodes);
        System.err.println(list);
    }
}

上面这个是递归创建树形结构的基本思路和代码,但是不能当成工具类使用,下面是将整个建树的过程进行封装抽取成一套工具类的过程:
1、这个是抽取的返回的树形结构对象:基本结构是对象及下面的子对象集合,如果有多层就封装在children中

@Data
public class Ztree<T> {
    private T t;
    private List<T> children;
}

2、对实体的抽取和封装,BaseEntity可以用来抽取数据库建表是的必填字段(id,create_time,update_time,del),IBaseTree抽取的是针对的树形结构的数据,一般都是自关联的表,有pid字段的,Type 就是实体类,用来继承和实现需要的Base类/接口

@Data
public abstract class BaseEntity<E> implements Serializable {
    @Id
    @JsonSerialize(using = ToStringSerializer.class)
    @GeneratedValue(generator = "JDBC")
    private E id;
}

public interface IBaseTree {

    void setPid(Integer pid);
    Integer getPid();

}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Type extends BaseEntity<Integer> implements IBaseTree {

    private Integer pid;
    private String name;
}

3 、工具类的抽取

public class TreeUtil {
	  /**
     * 
     * @param list  传入查询到的所有的list数据
     * @return  返回Ztree的list对象,已经转换成树形结构
     */
    public static <T extends BaseEntity & IBaseTree> List<Ztree> getTree(List<T> list){
        List<Ztree> res = new ArrayList<>();
        List<T> collect = list.stream().filter(p -> p.getPid() == 0).collect(Collectors.toList());
        for (T t : collect) {
            Ztree ztree = new Ztree();
            setZtree(t, list, ztree);
            res.add(ztree);
        }
        return res;
    }

    /**
     * @param t 
     * @param list  整个数据的list集合
     * @param ztree
     */
    private static <T extends BaseEntity & IBaseTree> void setZtree(T t, List<T> list, Ztree ztree) {
        ztree.setT(t);
        ztree.setChildren(getChildrens(t, list));
    }

    /**
     * 
     * @param t
     * @param list  整个数据的list集合
     * @return
     */
    private static <T extends BaseEntity & IBaseTree> List getChildrens(T t, List<T> list) {
        List res = new ArrayList<>();
        for (T l : list) {
            Ztree ztree = new Ztree();
            if(Objects.equals(l.getPid(), t.getId())){
                setZtree(l, list, ztree);
                res.add(ztree);
            }
        }
        return res;
    }
}

4、单元测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class ServiceControllerTest {
	@Test
    public void test01() throws Exception {
    	Type type1 = new Type(0,"湖北");
        type1.setId(1);
        Type type2 = new Type(0,"湖南");
        type2.setId(2);
        Type type3 = new Type(1,"武汉");
        type3.setId(3);
        Type type4 = new Type(1,"黄冈");
        type4.setId(4);
        Type type5 = new Type(2,"长沙");
        type5.setId(5);
        Type type6 = new Type(4,"黄梅");
        type6.setId(6);

        List<Type> list = Arrays.asList(type1,type2,type3,type4,type5,type6);
        List<Ztree> ztrees = TreeUtil.getTree(list);
        System.err.println(ztrees);
    }
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值