创建树公共接口

/**
 * 树公共接口
 * 需要包装成树形结构的实体继承此类,并添加List<T> children属性
 *
 * @author jinlong
 * @date 2019-06-28
 */
public interface TreeMixin<T> {
    /**
     * 获取子节点
     *
     * @return List
     */
    List<T> getChildren();

    /**
     * 设置子节点
     *
     * @param children 子节点列表
     */
    void setChildren(List<T> children);

    /**
     * 添加子节点
     *
     * @param child 子节点
     */
    default void addChild(T child) {
        List<T> children = getChildren();
        if (children == null) {
            children = new ArrayList<>();
        }
        children.add(child);
    }
}

创建返回树结构实体类

@Data
public class DepartDto implements TreeMixin<DepartDto> {
    /**
     * DepartDto的唯一标识
     */
    private String key;
    private Long id;
    private String name;
    /**
     * 可以是员工工号或部门代码
     */
    private String code;
    private Long parentId;

    /**
     * 子部门
     */
    private List<DepartDto> children = new ArrayList<>();


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

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

    /**
     * 
     * @param depart
     */
    public void fillDepart(Department depart){
        this.setKey("d"+depart.getId());
        this.setName(depart.getName());
        this.setParentId(depart.getParentId());
        this.setId(depart.getId());
    }

创建树辅助类

/**
 * 树辅助类
 *
 * @param <T> 节点类型
 * @param <R> id类型
 * @author jinlong
 * @date 2019-06-28
 */
public class TreeUtil<T extends TreeMixin, R> {
    /**
     * id获取方法
     */
    private Function<T, R> idGetter;
    /**
     * 父节点id获取方法
     */
    private Function<T, R> parentIdGetter;

    public TreeUtil(Function<T, R> idGetter, Function<T, R> parentIdGetter) {
        this.idGetter = idGetter;
        this.parentIdGetter = parentIdGetter;
    }

    /**
     * 转化为树形结构
     *
     * @return
     */
    public T buildTree(List<T> list, T root) {
        List<T> children = buildTreeList(list, idGetter.apply(root));
        root.setChildren(children);
        return root;
    }

    /**
     * 构建树
     *
     * @param list 待转化的数据列表
     * @return
     */
    public List<T> buildTreeList(List<T> list, R rootId) {
        ArrayList<T> dest = new ArrayList<>(Collections.nCopies(list.size(), null));
        Collections.copy(dest, list);
        Map<R, T> idItemsMap = dest.stream().collect(Collectors.toMap(item -> idGetter.apply(item), item -> item));
        dest.forEach(item -> {
            R parentId = parentIdGetter.apply(item);
            Optional.ofNullable(idItemsMap.get(parentId)).ifPresent(parent -> parent.addChild(item));
        });
        return dest.stream().peek(d -> {
            if (CollectionUtils.isEmpty(d.getChildren())) {
                d.setChildren(null);
            }
        }).filter(matchParentId(rootId)).collect(Collectors.toList());
    }

    private Predicate<T> matchParentId(R parentId) {
        return item -> Objects.equals(parentIdGetter.apply(item), parentId);
    }
}

获取树形结构具体方法 这是具体流程 获取什么数据还需根据自己的业务来获取

  /**
     * 查询组织架构数据(部门加员工)
     * @param onlyWorking 是否只查询在职的
     * @return
     */
    public DepartDto treeHasEmployee(Boolean onlyWorking) {
        //获取全部的部门列表
        List<Department> list = findAll();
        //获取根部门 
        Department rootDept = findRoot();
        //获取根部门id
        Long rootId = rootDept.getId();
        //创建树形结构数据对象
        DepartDto root = new DepartDto();
        //获取全部员工
        List<WorkInfo> userList = workInfoService.list();
        //创建一个和员工集合大小一样的集合 泛型为树形结构的实体类
        List<DepartDto> dtoList =Lists.newArrayListWithExpectedSize(userList.size());
        //将员工集合转换为树形结构的实体类
        userList.forEach(u -> {
            DepartDto dto = new DepartDto();
            dto.setKey(u.getId().toString());
            dto.setName(u.getName());
            dto.setParentId(u.getDepartmentId());
            dto.setId(u.getId());
            dto.setCode(u.getJobNumber());
            dtoList.add(dto);
        });
        //将部门集合转换为树形结构的实体类
        for (Department d : list) {
            //判断是否为根节点
            if (d.getId().equals(rootId)) {
            //为根节点时 将数据转换为树形结构不做任何操作
                root.fillDepart(d);
            } else {
            //为子节点   将数据转换为树形结构并且加入到dtoList中
                DepartDto dto = new DepartDto();
                dto.fillDepart(d);
                dtoList.add(dto);
            }
        }
        //创建树形工具类对象 调用树形工具全参构造方法参数为 参数为:
        //@param  getId方法  获取数据id方法
        //@param getParentId方法  获取父id方法
        TreeUtil<DepartDto, Long> treeUtil = new TreeUtil<>(DepartDto::getId, DepartDto::getParentId);
        //调用树形工具类的buildTree方法 参数是 
        // @param dtoList 所有子节点集合 泛型为树形结构实体类
        // @param root  根部门
        return treeUtil.buildTree(dtoList, root);

Tony猿
25 声望4 粉丝

« 上一篇
vue下载文件