创立树公共接口
/**
* 树公共接口
* 须要包装成树形构造的实体继承此类,并增加 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);