java后端操作樹結(jié)構(gòu)的案例代碼
一、樹結(jié)構(gòu)的三種組裝方式(遞歸.雙層for循環(huán),map)
(1)遞歸
普通遞歸方法
public Result getBmsMenuList(UserSessionVO userSessionInfo) { // 查詢頂級(jí)節(jié)點(diǎn)菜單 List<BmsMenuVO> bmsMenuVOList = bmsMenuDao.selectBmsMenuList(new BmsMenuQueryConditionVO()); for (BmsMenuVO bmsMenuVO : bmsMenuVOList) { getBmsMenuListByRecursion(bmsMenuVO); } return Result.createWithModels(null, bmsMenuVOList); } private void getBmsMenuListByRecursion(BmsMenuVO bmsMenuVO) { List<BmsMenuVO> bmsMenuVOS = bmsMenuDao.selectBmsMenuList(new BmsMenuQueryConditionVO().setParentId(bmsMenuVO.getId())); if (CollectionUtils.isEmpty(bmsMenuVOS)) { return; } bmsMenuVO.setChildBmsMenuList(bmsMenuVOS); for (BmsMenuVO menuVO : bmsMenuVOS) { getBmsMenuListByRecursion(menuVO); } }
stream流遞歸方法
//獲取父節(jié)點(diǎn) List<TreeSelect> collect = trees.stream().filter(m -> m.getParentId() == 0).map( (m) -> { m.setChildren(getChildrenList(m, trees)); return m; } ).collect(Collectors.toList()); /** * 獲取子節(jié)點(diǎn)列表 * @param tree * @param list * @return */ public static List<TreeSelect> getChildrenList(TreeSelect tree, List<TreeSelect> list){ List<TreeSelect> children = list.stream().filter(item -> Objects.equals(item.getParentId(), tree.getId())).map( (item) -> { item.setChildren(getChildrenList(item, list)); return item; } ).collect(Collectors.toList()); return children; }
(2)雙層for循環(huán)
// 查詢主節(jié)點(diǎn) List<BmsMenuVO> bmsMenuVOList = bmsRoleMenuDao.getAllRoleMenuList(condition); // 拼裝結(jié)果 List<BmsMenuVO> bmsMenuTree = new ArrayList<>(); for (BmsMenuVO bmsMenuVO : bmsMenuVOList) { // 根節(jié)點(diǎn)的父Id為null if (bmsMenuVO.getParentId() == null) { bmsMenuTree.add(bmsMenuVO); } for (BmsMenuVO menuVO : bmsMenuVOList) { if (menuVO.getParentId() != null && menuVO.getParentId().equals(bmsMenuVO.getId())) { if (CollectionUtils.isEmpty(bmsMenuVO.getChildBmsMenuList())) { bmsMenuVO.setChildBmsMenuList(new ArrayList<>()); } bmsMenuVO.getChildBmsMenuList().add(menuVO); } } } // 返回結(jié)果 return Result.createWithModels(null, bmsMenuTree);
(3)map遍歷
// 查詢所有節(jié)點(diǎn) List<BmsMenuVO> bmsMenuVOList = bmsRoleMenuDao.getAllRoleMenuList(condition); // 拼裝結(jié)果 List<BmsMenuVO> bmsMenuTree = new ArrayList<>(); // 用來存儲(chǔ)節(jié)點(diǎn)的子元素map Map<Long, BmsMenuVO> childBmsMenuMap = new LinkedHashMap<>(); for (BmsMenuVO menuVO : bmsMenuVOList) { childBmsMenuMap.put(menuVO.getId(), menuVO); } for (Long bmsMenuId : childBmsMenuMap.keySet()) { BmsMenuVO menuVO = childBmsMenuMap.get(bmsMenuId); Long parentId = menuVO.getParentId(); if (parentId == null) { bmsMenuTree.add(menuVO); } else { BmsMenuVO parentMenuVO = childBmsMenuMap.get(parentId); if (parentMenuVO.getChildBmsMenuList() == null) { parentMenuVO.setChildBmsMenuList(new ArrayList<>()); } parentMenuVO.getChildBmsMenuList().add(menuVO); } }
2、使用遞歸查詢某個(gè)節(jié)點(diǎn)所在的樹結(jié)構(gòu)
使用場景:當(dāng)我們得到一個(gè)樹形結(jié)構(gòu)數(shù)據(jù)時(shí),可能需要在樹形結(jié)構(gòu)上對(duì)數(shù)據(jù)進(jìn)行篩選,例如通過文件夾(文件)名稱模糊查詢相關(guān)的文件夾并展現(xiàn)其父級(jí)。
缺點(diǎn):需要查詢出完整的樹形結(jié)構(gòu)才能用作篩選,在數(shù)據(jù)量非常龐大的時(shí)候并不適用。
@Data public class TreeDto { private String id; private String name; private List<TreeDto> subsetTreeDtoList; public TreeDto(String id,String name,List<TreeDto> subsetTreeDtoList){ this.id = id; this.name = name; this.subsetTreeDtoList = subsetTreeDtoList; } }
篩選
/** * 樹形篩選查找 * @param treeDtoList 樹形集合 * @param idList 篩選條件(可以是其他條件) * @return 包含的節(jié)點(diǎn)數(shù)據(jù) */ public static List<TreeDto> screenTree(List<TreeDto> treeDtoList, List<String> idList){ //最后返回的篩選完成的集合 List<TreeDto> screeningOfCompleteList = new ArrayList<>(); if (listIsNotEmpty(treeDtoList) && listIsNotEmpty(idList)){ for (TreeDto treeDto : treeDtoList){ List<TreeDto> subsetList = treeDto.getSubsetTreeDtoList(); //遞歸篩選完成后的返回的需要添加的數(shù)據(jù) TreeDto addTreeDto = getSubsetPmsPlanPo(treeDto,subsetList,idList); if (isNotEmpty(addTreeDto)){ screeningOfCompleteList.add(addTreeDto); } } return screeningOfCompleteList; } return null; } /** * 篩選符合的集合并返回 * @param treeDto 樹形類 * @param subsetTreeDtoList 子集集合 * @param idList 篩選條件 * @return 篩選成功的類 */ public static TreeDto getSubsetPmsPlanPo(TreeDto treeDto,List<TreeDto> subsetTreeDtoList,List<String> idList){ //作為篩選條件的判斷值 String id = treeDto.getId(); //有子集時(shí)繼續(xù)向下尋找 if (listIsNotEmpty(subsetTreeDtoList)){ List<TreeDto> addTreeDtoList = new ArrayList<>(); for (TreeDto subsetTreeDto : subsetTreeDtoList){ List<TreeDto> subsetList = subsetTreeDto.getSubsetTreeDtoList(); TreeDto newTreeDto = getSubsetPmsPlanPo(subsetTreeDto,subsetList,idList); //當(dāng)子集篩選完不為空時(shí)添加 if (isNotEmpty(newTreeDto)){ addTreeDtoList.add(newTreeDto); } } //子集滿足條件篩選時(shí)集合不為空時(shí),替換對(duì)象集合內(nèi)容并返回當(dāng)前對(duì)象 if (listIsNotEmpty(addTreeDtoList)){ treeDto.setSubsetTreeDtoList(addTreeDtoList); return treeDto; //當(dāng)前對(duì)象子集對(duì)象不滿足條件時(shí),判斷當(dāng)前對(duì)象自己是否滿足篩選條件,滿足設(shè)置子集集合為空,并返回當(dāng)前對(duì)象 }else if (listIsEmpty(addTreeDtoList) && idList.contains(id)){ treeDto.setSubsetTreeDtoList(null); return treeDto; }else { //未滿足篩選條件直接返回null return null; } }else { //無子集時(shí)判斷當(dāng)前對(duì)象是否滿足篩選條件 if (idList.contains(id)){ return treeDto; }else { return null; } } } /** * 判斷集合為空 * @param list 需要判斷的集合 * @return 集合為空時(shí)返回 true */ public static boolean listIsEmpty(Collection list){ return (null == list || list.size() == 0); } /** * 判斷集合非空 * @param list 需要判斷的集合 * @return 集合非空時(shí)返回 true */ public static boolean listIsNotEmpty(Collection list){ return !listIsEmpty(list); } /** * 判斷對(duì)象為null或空時(shí) * @param object 對(duì)象 * @return 對(duì)象為空或null時(shí)返回 true */ public static boolean isEmpty(Object object) { if (object == null) { return (true); } if ("".equals(object)) { return (true); } if ("null".equals(object)) { return (true); } return (false); } /** * 判斷對(duì)象非空 * @param object 對(duì)象 * @return 對(duì)象為非空時(shí)返回 true */ public static boolean isNotEmpty(Object object) { if (object != null && !object.equals("") && !object.equals("null")) { return (true); } return (false); } public static void main(String[] args) { TreeDto treeDto1 = new TreeDto("1","A",new ArrayList<TreeDto>()); TreeDto treeDto1_1 = new TreeDto("1.1","A-A",new ArrayList<TreeDto>()); TreeDto treeDto1_2 = new TreeDto("1.2","A-B",new ArrayList<TreeDto>()); TreeDto treeDto1_3 = new TreeDto("1.3","A-C",new ArrayList<TreeDto>()); treeDto1.getSubsetTreeDtoList().add(treeDto1_1); treeDto1.getSubsetTreeDtoList().add(treeDto1_2); treeDto1.getSubsetTreeDtoList().add(treeDto1_3); TreeDto treeDto2 = new TreeDto("2","B",new ArrayList<TreeDto>()); TreeDto treeDto2_1 = new TreeDto("2.1","B-A",new ArrayList<TreeDto>()); TreeDto treeDto2_2 = new TreeDto("2.2","B-B",new ArrayList<TreeDto>()); TreeDto treeDto2_3 = new TreeDto("2.3","B-C",new ArrayList<TreeDto>()); TreeDto treeDto2_3_1 = new TreeDto("2.3.1","B-C-A",null); treeDto2.getSubsetTreeDtoList().add(treeDto2_1); treeDto2.getSubsetTreeDtoList().add(treeDto2_2); treeDto2.getSubsetTreeDtoList().add(treeDto2_3); treeDto2.getSubsetTreeDtoList().get(2).getSubsetTreeDtoList().add(treeDto2_3_1); String[] array = {"1.3","2.2","2.3.1"}; List<String> idList = Arrays.asList(array); List<TreeDto> treeDtoList = new ArrayList<>(); treeDtoList.add(treeDto1); treeDtoList.add(treeDto2); System.out.println(JSON.toJSONString(screenTree(treeDtoList,idList))); } }
返回結(jié)果為
到此這篇關(guān)于java后端操作樹結(jié)構(gòu)的文章就介紹到這了,更多相關(guān)java樹結(jié)構(gòu)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解Java構(gòu)建樹結(jié)構(gòu)的公共方法
- Java實(shí)現(xiàn)遞歸查詢樹結(jié)構(gòu)的示例代碼
- java樹結(jié)構(gòu)stream工具類的示例代碼詳解
- java合成模式之神奇的樹結(jié)構(gòu)
- JAVA使用hutool工具實(shí)現(xiàn)查詢樹結(jié)構(gòu)數(shù)據(jù)(省市區(qū))
- JAVA如何轉(zhuǎn)換樹結(jié)構(gòu)數(shù)據(jù)代碼實(shí)例
- JAVA后臺(tái)轉(zhuǎn)換成樹結(jié)構(gòu)數(shù)據(jù)返回給前端的實(shí)現(xiàn)方法
- Java實(shí)現(xiàn)簡單樹結(jié)構(gòu)
相關(guān)文章
Java中Lambda表達(dá)式的進(jìn)化之路詳解
本文通過示例大家給大家介紹了Java中Lambda表達(dá)式的進(jìn)化之路,感興趣的的朋友一起看看吧,希望能夠給你帶來幫助2021-11-11SpringBoot整合liquibase的實(shí)現(xiàn)方法
這篇文章主要介紹了SpringBoot整合liquibase的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Java中的springboot監(jiān)聽事件和處理事件詳解
這篇文章主要介紹了Java中的springboot監(jiān)聽事件和處理事件,這個(gè)示例展示了如何在Spring Boot應(yīng)用中定義自定義事件、發(fā)布事件以及監(jiān)聽事件,需要的朋友可以參考下2024-07-07Spring中@ControllerAdvice注解的用法解析
這篇文章主要介紹了Spring中@ControllerAdvice注解的用法解析,顧名思義,@ControllerAdvice就是@Controller 的增強(qiáng)版,@ControllerAdvice主要用來處理全局?jǐn)?shù)據(jù),一般搭配@ExceptionHandler、@ModelAttribute以及@InitBinder使用,需要的朋友可以參考下2023-10-10如何解決IDEA中JSP頁面部分出現(xiàn)綠色背景色問題
這篇文章主要介紹了如何解決IDEA中JSP頁面部分出現(xiàn)綠色背景色問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12