1.常规代码实现
/**
* @Author: liftsail
* @Date: 2022/9/16 15:38
* @Description: 不积跬步无以至千里
*/
public class MenuTreeUtil {
//建立树形结构
public static <T extends MenuTreeNode> List<? extends MenuTreeNode> buildTree(List<? extends MenuTreeNode> detailDOS) {
List<MenuTreeNode> treeMenus = new ArrayList<>();
for (MenuTreeNode menuNode : getRootNode(detailDOS)) {
menuNode = buildChildTree(menuNode, detailDOS);
treeMenus.add(menuNode);
}
return treeMenus;
}
//递归,建立子树形结构
private static MenuTreeNode buildChildTree(MenuTreeNode pNode, List<? extends MenuTreeNode> detailDOS) {
List<MenuTreeNode> childMenus = new ArrayList<>();
for (MenuTreeNode menuNode : detailDOS) {
if (menuNode.getParentNode().equals(pNode.getNode())) {
childMenus.add(buildChildTree(menuNode, detailDOS));
}
}
if (CollectionUtils.isNotEmpty(childMenus)) {
pNode.setChildren(childMenus);
}
return pNode;
}
//获取根节点
private static List<? extends MenuTreeNode> getRootNode(List<? extends MenuTreeNode> detailDOS) {
List<MenuTreeNode> rootMenuLists = new ArrayList<>();
for (MenuTreeNode menuNode : detailDOS) {
if (menuNode.getParentNode().equals("0")) {
rootMenuLists.add(menuNode);
}
}
return rootMenuLists;
}
/**
* 将树状结构转换为平铺数据结构(将含有children的树状结构转换为仅有节点和父节点的对象列表)
*
* @param detailDOS 树状结构数据列表
* @param <T> 任意类型参数
* @return 平铺数据结构列表
*/
public static <T extends MenuTreeNode> List<? extends MenuTreeNode> convertToObjList(List<? extends MenuTreeNode> detailDOS) {
List<MenuTreeNode> treeMenus = new ArrayList<>();
for (MenuTreeNode menuNode : detailDOS) {
if (menuNode.getChildren() != null) {
treeMenus.add(menuNode);
convertToObjList(menuNode.getChildren(), treeMenus);
} else {
treeMenus.add(menuNode);
}
}
return treeMenus;
}
public static <T extends MenuTreeNode> void convertToObjList(List<? extends MenuTreeNode> source,
List<MenuTreeNode> outList) {
if (outList == null) {
outList = new ArrayList<>();
}
for (MenuTreeNode tTreeStructure : source) {
if (tTreeStructure.getChildren() != null) {
outList.add(tTreeStructure);
convertToObjList(tTreeStructure.getChildren(), outList);
} else {
outList.add(tTreeStructure);
}
}
}
2.lambda实现
/**
* 展示目录树
*
* @param userId
* @return
*/
public DirTreeNode dirTree(Long userId) {
List<UserFileEntity> userFileList = userFileRepository.findAllByUserIdAndDirAndDelete(userId, true, false);
DirTreeNode rootNode = DirTreeNode.root();//目录树根节点
//lambda表达式实现树形结构 1.过滤器2.map数据转换3.创建节点时通过子节点结合进行递归逻辑
rootNode.setChildren(
userFileList.parallelStream().filter(uf -> Objects.isNull(uf.getPid())).map(uf ->
DirTreeNode.create(uf, 1L, getDirChildrenTree(uf.getId(), 2L, userFileList))
).collect(Collectors.toList())
);
return rootNode;
}
/**
* 递归获取子目录
*
* @param pid
* @param depth
* @param userFileEntityList
* @return
*/
private List<DirTreeNode> getDirChildrenTree(String pid, Long depth, List<UserFileEntity> userFileEntityList) {
return userFileEntityList.parallelStream().filter(uf -> pid.equals(uf.getPid())).map(uf ->
DirTreeNode.create(uf, depth, getDirChildrenTree(uf.getId(), depth + 1, userFileEntityList))
).collect(Collectors.toList());
}
---
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "目录树")
public class DirTreeNode {
@Schema(description = "用户文件id")
private String id;
@JsonProperty("label")
@Schema(description ="用户文件名")
private String filename;
@Schema(description = "所在目录,根目录为null")
private String pid;
@Schema(description = "深度")
private Long depth;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@Schema(description = "子目录")
private List<DirTreeNode> children;
public static DirTreeNode root(){
return new DirTreeNode(null, StringPool.SLASH, null, 0L, null);
}
public static DirTreeNode create(UserFileEntity userFileEntity, Long depth, List<DirTreeNode> children){
return new DirTreeNode(userFileEntity.getId(), userFileEntity.getFilename(), userFileEntity.getPid(), depth, children);
}
}
3.简洁实现(推荐)
public List<MineResCatalogVO> queryLeftMenuByTeaIdAndType(Integer teaId, Integer type) {
List<MineResCatalogVO> mineResCatalogVOList = mineResCatalogMapper.queryLeftMenuByTeaIdAndType(teaId, type);
List<MineResCatalogVO> treeEX = getTreeEX(mineResCatalogVOList);
return treeEX;
}
public static List<MineResCatalogVO> getTreeEX(List<MineResCatalogVO> record) {
return record.stream().filter(mineResCatalogVO -> {
return 0 == (mineResCatalogVO.getPid());
}).map(mineResCatalogVO -> {
List<MineResCatalogVO> childEX = getChildEX(mineResCatalogVO.getCatalogId(), record, 1);
mineResCatalogVO.setMenuChildren(childEX);
return mineResCatalogVO;
}).collect(Collectors.toList());
}
private static List<MineResCatalogVO> getChildEX(Integer catalogId, List<MineResCatalogVO> record, Integer depth) {
return record.stream().filter(mineResCatalogVO -> {
return catalogId == (mineResCatalogVO.getPid());
}).map(mineResCatalogVO -> {
mineResCatalogVO.setDepth(depth);
List<MineResCatalogVO> childEX = getChildEX(mineResCatalogVO.getCatalogId(), record, depth + 1);
mineResCatalogVO.setMenuChildren(childEX);
return mineResCatalogVO;
}).collect(Collectors.toList());
}