java父子節(jié)點parentid樹形結(jié)構(gòu)數(shù)據(jù)的規(guī)整
java父子節(jié)點parentid樹形結(jié)構(gòu)數(shù)據(jù)
這幾天寫一個父子節(jié)點的數(shù)據(jù)規(guī)整,在網(wǎng)上找了一些方法,都太繁瑣,自己寫了一個,感覺比較簡單
先說一下原理
第一,我們從數(shù)據(jù)庫中將需要的數(shù)據(jù)查詢出來,得到一個Object集合的list
第二,定義一個map,key為id,value為Object,這個的目的是為了方便后面的查找
第三,遍歷第一步中查詢到的數(shù)據(jù)集合list,取出Object中的parentid,根據(jù)parentid從第二步map中取出它的父節(jié)點,將其放入到父節(jié)點中去
第四,刪除map中父節(jié)點parentid不為空的數(shù)據(jù),這樣我們的數(shù)據(jù)結(jié)構(gòu)就組成了。
這里主要使用了java在參數(shù)傳遞時,如果參數(shù)是一個object時,那么它傳遞的是引用這么一個思想來進行實現(xiàn),貼出代碼供大家參考
public class Test {
public List<Goal> test(List<Goal> listGoal) {
Map<Integer, Goal> goalMap = new HashMap<Integer, Goal>();
for (Goal g : listGoal) {
int id = g.getId();
goalMap.put(id, g);
}
for (Goal g : listGoal) {
int pid = g.getParentId();
if (pid != 0) {
Goal tempGoal = goalMap.get(pid);
List<Goal> tempListGoal = tempGoal.getListGoal();
if (tempListGoal == null) {
tempListGoal = new ArrayList<Goal>();
}
tempListGoal.add(g);
tempGoal.setListGoal(tempListGoal);
}
}
List<Integer> list = new ArrayList<Integer>();
for (Integer k : goalMap.keySet()) {
Goal tempGoal = goalMap.get(k);
if (tempGoal.getParentId() != 0) {
list.add(k);
}
}
for (int i : list) {
goalMap.remove(i);
}
return new ArrayList<Goal>(goalMap.values());
}
public static void main(String[] args) {
List<Goal> listGoal = new ArrayList<Goal>();
Goal g1 = new Goal();
g1.setId(1);
g1.setParentId(0);
g1.setGoalName("g1");
Goal g2 = new Goal();
g2.setId(2);
g2.setParentId(1);
g2.setGoalName("g2");
Goal g3 = new Goal();
g3.setId(3);
g3.setParentId(2);
g3.setGoalName("g3");
Goal g4 = new Goal();
g4.setId(4);
g4.setParentId(2);
g4.setGoalName("g4");
Goal g5 = new Goal();
g5.setId(5);
g5.setParentId(3);
g5.setGoalName("g5");
Goal g6 = new Goal();
g6.setId(6);
g6.setParentId(0);
g6.setGoalName("g6");
Goal g7 = new Goal();
g7.setId(7);
g7.setParentId(3);
g7.setGoalName("g7");
Goal g8 = new Goal();
g8.setId(8);
g8.setParentId(7);
g8.setGoalName("g8");
Goal g9 = new Goal();
g9.setId(9);
g9.setParentId(7);
g9.setGoalName("g9");
Goal g10 = new Goal();
g10.setId(10);
g10.setParentId(4);
g10.setGoalName("g10");
Goal g11 = new Goal();
g11.setId(11);
g11.setParentId(10);
g11.setGoalName("g1");
Goal g12 = new Goal();
g12.setId(12);
g12.setParentId(7);
g12.setGoalName("g12");
Goal g13 = new Goal();
g13.setId(13);
g13.setParentId(0);
g13.setGoalName("g13");
listGoal.add(g1);
listGoal.add(g2);
listGoal.add(g3);
listGoal.add(g4);
listGoal.add(g5);
listGoal.add(g6);
listGoal.add(g7);
listGoal.add(g8);
listGoal.add(g9);
listGoal.add(g10);
listGoal.add(g11);
listGoal.add(g12);
listGoal.add(g13);
Test t = new Test();
List<Goal> listT = t.test(listGoal);
System.out.println(listT);
}java將有父子關(guān)系的數(shù)據(jù)轉(zhuǎn)換成樹形結(jié)構(gòu)數(shù)據(jù)
數(shù)據(jù)庫父子結(jié)構(gòu)數(shù)據(jù)設(shè)計
大部分采用 parentId的形式來存儲父id,并且只存儲父id,祖父Id不存儲。也可以添加存儲層級級別或者層級關(guān)系等字段。
CREATE TABLE `t_resource` ( `id` varchar(255) NOT NULL COMMENT '主鍵', `parent_id` varchar(255) DEFAULT NULL COMMENT '父ID', `name` varchar(255) DEFAULT NULL COMMENT '名稱', `url` varchar(255) DEFAULT NULL COMMENT '資源url', `level` varchar(255) DEFAULT NULL COMMENT '層級級別', `decode` varchar(255) DEFAULT NULL COMMENT '層級ID的關(guān)系,用”_“分割', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

將有父子關(guān)系的數(shù)據(jù)轉(zhuǎn)換成樹形結(jié)構(gòu)數(shù)據(jù)
mapper層獲取數(shù)據(jù)庫數(shù)據(jù)和 controller層處理很簡單,將有父子關(guān)系的數(shù)據(jù)轉(zhuǎn)換成樹形結(jié)構(gòu)數(shù)據(jù)交給 service層處理。
@PostMapping("/getMuneTree")
@ResponseBody
public ResponseEntity<Map<String, Object>> getMuneTree(){
Map<String, Object> map = new HashMap<>();
map.put("menuList", resourceDOService.getMuneTree());
return ResponseEntity.ok(map);
} 
1、方式一:遞歸:從樹的最頂級獲取子級,然后子級獲取其子級。
返回時,需要哪些字段值就添加哪些字段值到 map中。結(jié)果圖如上
/**
* 將有父子關(guān)系的數(shù)據(jù)轉(zhuǎn)換成樹形結(jié)構(gòu)數(shù)據(jù)
*
* @return 最終的樹狀結(jié)構(gòu)的集合數(shù)據(jù)
*/
@Override
public List<Map<String, Object>> getMuneTree() {
// 獲取數(shù)據(jù)庫中帶有有父子關(guān)系的數(shù)據(jù)
List<ResourceDO> data = resourceDOMapper.selectAll();
//創(chuàng)建一個List集合來存放最終的樹狀結(jié)構(gòu)數(shù)據(jù)
List<Map<String, Object>> menuList = new ArrayList<>();
// 先存入最頂級的樹(0代表沒有父級,即最頂級),然后通過最頂級的id遞歸獲取子級
for (ResourceDO entity : data) {
Map<String, Object> map = new HashMap<>();
if ("0".equals(entity.getParentId())) {
map.put("id", entity.getId());
map.put("parentId", entity.getParentId());
map.put("name", entity.getName());
map.put("children", getChildren(data, entity.getId()));
menuList.add(map);
}
}
return menuList;
}
/**
* 遞歸處理:通過id獲取子級,查詢子級下的子級
*
* @param data 數(shù)據(jù)庫的原始數(shù)據(jù)
* @param id 主id
* @return 該id下得子級
*/
public List<Map<String, Object>> getChildren(List<ResourceDO> data, String id) {
List<Map<String, Object>> list = new ArrayList<>();
if (data == null || data.size() == 0 || id == null) {
return list;
}
for (ResourceDO entity : data) {
Map<String, Object> map = new HashMap<>();
//如果本級id與數(shù)據(jù)的父id相同,就說明是子父級關(guān)系
if (id.equals(entity.getParentId())) {
map.put("id", entity.getId());
map.put("parentId", entity.getParentId());
map.put("name", entity.getName());
//查詢子級下的子級
map.put("children", getChildren(data, entity.getId()));
list.add(map);
}
}
return list;
}2、方式二:組裝帶有children關(guān)聯(lián)性的對象
在實體列中定義一個 children集合:
private List<ResourceDO> children = new ArrayList<>();
返回的是實體類對象的所有值,這里操作的都是集合存儲對象的引用
/**
* 將有父子關(guān)系的數(shù)據(jù)轉(zhuǎn)換成樹形結(jié)構(gòu)數(shù)據(jù)
*
* @return 最終的樹狀結(jié)構(gòu)的集合數(shù)據(jù)
*/
@Override
public List<ResourceDO> getMuneTree2() {
// 獲取數(shù)據(jù)庫中帶有有父子關(guān)系的數(shù)據(jù)
List<ResourceDO> data = resourceDOMapper.selectAll();
// 復(fù)制data數(shù)據(jù)
List<ResourceDO> menuList = new ArrayList<>(data);
// 遍歷兩次data來組裝帶有children關(guān)聯(lián)性的對象,如果找到子級就刪除menuList的數(shù)據(jù)
for (ResourceDO entity : data) {
for (ResourceDO entity2 : data) {
//如果本級id與數(shù)據(jù)的父id相同,就說明是子父級關(guān)系
if (entity.getId().equals(entity2.getParentId())) {
entity.getChildren().add(entity2);
menuList.remove(entity2);
}
}
}
return menuList;
}總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
- Java 遞歸查詢部門樹形結(jié)構(gòu)數(shù)據(jù)的實踐
- java返回前端樹形結(jié)構(gòu)數(shù)據(jù)的2種實現(xiàn)方式
- 詳解如何使用Java流API構(gòu)建樹形結(jié)構(gòu)數(shù)據(jù)
- java遞歸實現(xiàn)樹形結(jié)構(gòu)數(shù)據(jù)完整案例
- Java?處理樹形結(jié)構(gòu)數(shù)據(jù)的過程
- Java樹形結(jié)構(gòu)數(shù)據(jù)生成導(dǎo)出excel文件方法記錄
- Java如何使用遞歸查詢多級樹形結(jié)構(gòu)數(shù)據(jù)(多級菜單)
相關(guān)文章
SpringBoot中注冊Bean的10種方式總結(jié)
在Spring Boot應(yīng)用中,Bean是構(gòu)成應(yīng)用的核心組件,Spring容器負責(zé)管理這些Bean,包括它們的創(chuàng)建、配置、組裝、管理和銷毀,在Spring Boot中,有多種方式可以注冊Bean,本文將詳細介紹這些不同的注冊方式,并給出相應(yīng)的示例代碼和適用場景,需要的朋友可以參考下2024-08-08
淺析如何在SpringBoot中實現(xiàn)數(shù)據(jù)脫敏
脫敏是指在不改變原數(shù)據(jù)結(jié)構(gòu)的前提下,通過某種方式處理數(shù)據(jù),使數(shù)據(jù)不能直接暴露用戶的真實信息,下面我們就來看看SpringBoot中實現(xiàn)數(shù)據(jù)脫敏的具體方法吧2024-03-03
解決Eclipse發(fā)布到Tomcat丟失依賴jar包的問題
這篇文章介紹了如何在Eclipse中配置部署裝配功能,以確保在將Web項目發(fā)布到Tomcat服務(wù)器時不會丟失任何依賴jar包,通過手動配置或使用構(gòu)建工具腳本,可以自動化這個過程,提高開發(fā)效率和應(yīng)用程序的穩(wěn)定性,感興趣的朋友跟隨小編一起看看吧2025-01-01
Java CountDownLatch應(yīng)用場景代碼實例
這篇文章主要介紹了Java CountDownLatch應(yīng)用場景代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09
Springboot微服務(wù)打包Docker鏡像流程解析
這篇文章主要介紹了Springboot微服務(wù)打包Docker鏡像流程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08

