java遞歸實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)數(shù)據(jù)完整案例
前言
本文提供兩種遞歸實(shí)現(xiàn)思路
樹(shù)形結(jié)構(gòu)數(shù)據(jù),大體的實(shí)現(xiàn)思路就是“父找子”,父節(jié)點(diǎn)去層層遞歸尋找子節(jié)點(diǎn),最后組裝成數(shù)據(jù)集合。
提示:以下是本篇文章正文內(nèi)容,下面案例可供參考
一、樹(shù)形結(jié)構(gòu)是什么?
樹(shù)形結(jié)構(gòu),和我們平常所觸及到的無(wú)限級(jí)菜單,是同一個(gè)道理。
所謂樹(shù)形結(jié)構(gòu),我們可以將其理解為:樹(shù)根或者樹(shù)冠,都可以無(wú)限分叉下去。
現(xiàn)有一張表,需要對(duì)表中數(shù)據(jù)進(jìn)行分級(jí)查詢(按照上下級(jí)關(guān)系進(jìn)行排列),我們常用的數(shù)據(jù)庫(kù)有: oracle和mysql;
如果使用oracle的話,使用connect by,很容易就能做到;
但是,mysql沒(méi)有現(xiàn)成的遞歸函數(shù),需要我們自己使用存儲(chǔ)過(guò)程封裝,而且,就算封裝好了遞歸函數(shù),mysql在執(zhí)行的時(shí)候,查詢速度會(huì)很慢。如何解決這個(gè)問(wèn)題呢?
既然數(shù)據(jù)庫(kù)不給力,我們只能交由程序來(lái)處理了,以減輕mysql數(shù)據(jù)庫(kù)的壓力。
二、實(shí)現(xiàn)方案
1、stream流遞歸實(shí)現(xiàn)
1.1 實(shí)體類
public class TreeBean {
/**
* id
*/
private Integer id;
/**
* 名稱
*/
private String name;
/**
* 父id ,根節(jié)點(diǎn)為0
*/
public Integer parentId;
/**
* 子節(jié)點(diǎn)信息
*/
public List<TreeBean> childList;
public TreeBean() {
}
public TreeBean(Integer id, String name, Integer parentId, List<TreeBean> childList) {
this.id = id;
this.name = name;
this.parentId = parentId;
this.childList = childList;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getParentId() {
return parentId;
}
public void setParentId(Integer parentId) {
this.parentId = parentId;
}
public List<TreeBean> getChildList() {
return childList;
}
public void setChildList(List<TreeBean> childList) {
this.childList = childList;
}
/**
* 初始化數(shù)據(jù)
* @return
*/
public List<TreeBean> initializationData() {
List<TreeBean> list = new ArrayList<>();
TreeBean t1 = new TreeBean(1, "廣東省", 0, new ArrayList<>());
TreeBean t2 = new TreeBean(2, "湖南省", 0, new ArrayList<>());
TreeBean t3 = new TreeBean(3, "廣州市", 1, new ArrayList<>());
TreeBean t4 = new TreeBean(4, "長(zhǎng)沙市", 2, new ArrayList<>());
TreeBean t5 = new TreeBean(5, "白云區(qū)", 3, new ArrayList<>());
TreeBean t6 = new TreeBean(6, "黃浦區(qū)", 3, new ArrayList<>());
TreeBean t7 = new TreeBean(7, "白云街道", 5, new ArrayList<>());
TreeBean t8 = new TreeBean(8, "深圳市", 1, new ArrayList<>());
TreeBean t9 = new TreeBean(9, "寶安區(qū)", 8, new ArrayList<>());
TreeBean t10 = new TreeBean(10, "福田區(qū)", 8, new ArrayList<>());
TreeBean t11 = new TreeBean(11, "南山區(qū)", 8, new ArrayList<>());
TreeBean t12 = new TreeBean(12, "南山街道", 11, new ArrayList<>());
TreeBean t13 = new TreeBean(13, "芙蓉區(qū)", 4, new ArrayList<>());
TreeBean t14 = new TreeBean(14, "岳麓區(qū)", 4, new ArrayList<>());
TreeBean t15 = new TreeBean(15, "開(kāi)福區(qū)", 4, new ArrayList<>());
TreeBean t16 = new TreeBean(16, "岳陽(yáng)市", 2, new ArrayList<>());
TreeBean t17 = new TreeBean(17, "岳麓街道", 14, new ArrayList<>());
list.add(t1);
list.add(t2);
list.add(t3);
list.add(t4);
list.add(t5);
list.add(t6);
list.add(t7);
list.add(t8);
list.add(t9);
list.add(t10);
list.add(t11);
list.add(t12);
list.add(t13);
list.add(t14);
list.add(t15);
list.add(t16);
list.add(t17);
return list;
}
}
1.2 實(shí)現(xiàn)類
/**
* 方式一:Stream流遞歸實(shí)現(xiàn)遍歷樹(shù)形結(jié)構(gòu)
*/
public static void treeTest1() {
//獲取數(shù)據(jù)
List<TreeBean> treeBeans = new TreeBean().initializationData();
//獲取父節(jié)點(diǎn)
List<TreeBean> collect = treeBeans.stream().filter(t -> t.getParentId() == 0).map(
m -> {
m.setChildList(getChildren(m, treeBeans));
return m;
}
).collect(Collectors.toList());
System.out.println(JSON.toJSONString(collect));
}
/**
* 遞歸查詢子節(jié)點(diǎn)
* @param root 根節(jié)點(diǎn)
* @param all 所有節(jié)點(diǎn)
* @return 根節(jié)點(diǎn)信息
*/
public static List<TreeBean> getChildren(TreeBean root, List<TreeBean> all) {
List<TreeBean> children = all.stream().filter(t -> {
return Objects.equals(t.getParentId(), root.getId());
}).map(
m -> {
m.setChildList(getChildren(m, all));
return m;
}
).collect(Collectors.toList());
return children;
}2、jdk1.7以下實(shí)現(xiàn)
2.1 節(jié)點(diǎn)類
便于提供前端取值

2.2 實(shí)現(xiàn)類


3、應(yīng)用場(chǎng)景
3.1 用于前端方便展示

3.2 用于查找并構(gòu)建子節(jié)點(diǎn)數(shù)據(jù)
以刪除菜單做例子,一般菜單未免會(huì)帶子菜單,所以,“父找子” 需求應(yīng)聲而來(lái);

代碼如下:


總結(jié)
資料參考:
- 鏈接1: java 樹(shù)形數(shù)據(jù)處理(Stream流和Map兩種方式實(shí)現(xiàn))
- 鏈接2: java 遞歸實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)的兩種實(shí)現(xiàn)方式
到此這篇關(guān)于java遞歸實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)數(shù)據(jù)的文章就介紹到這了,更多相關(guān)java遞歸樹(shù)形結(jié)構(gòu)數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MybatisPlus分頁(yè)查詢與多條件查詢介紹及查詢過(guò)程中空值問(wèn)題的解決
mybatisplus是個(gè)很好用的插件,相信小伙伴們都知道,下面這篇文章主要給大家介紹了關(guān)于mybatis-plus實(shí)現(xiàn)分頁(yè)查詢與多條件查詢介紹及查詢過(guò)程中空值問(wèn)題的相關(guān)資料,需要的朋友可以參考下2022-10-10
Java實(shí)現(xiàn)ATM機(jī)操作系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)ATM機(jī)操作系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
全網(wǎng)最全SpringBoot集成swagger的詳細(xì)教程
swagger是當(dāng)下比較流行的實(shí)時(shí)接口文文檔生成工具,swagger分為swagger2?和swagger3兩個(gè)常用版本,二者區(qū)別不是很大,主要對(duì)于依賴和注解進(jìn)行了優(yōu)化,swagger2需要引入2個(gè)jar包,swagger3只需要一個(gè),用起來(lái)沒(méi)有什么大的區(qū)別,本文給大家詳細(xì)介紹,感興趣的朋友一起看看吧2022-08-08
詳解使用@RequestBody取POST方式的json字符串
這篇文章主要介紹了詳解使用@RequestBody取POST方式的json字符串,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
SpringBoot2.6.x默認(rèn)禁用循環(huán)依賴后的問(wèn)題解決
由于SpringBoot從底層逐漸引導(dǎo)開(kāi)發(fā)者書寫規(guī)范的代碼,同時(shí)也是個(gè)憂傷的消息,循環(huán)依賴的應(yīng)用場(chǎng)景實(shí)在是太廣泛了,所以SpringBoot 2.6.x不推薦使用循環(huán)依賴,本文給大家說(shuō)下SpringBoot2.6.x默認(rèn)禁用循環(huán)依賴后的應(yīng)對(duì)策略,感興趣的朋友一起看看吧2022-02-02
java 實(shí)現(xiàn)通過(guò) post 方式提交json參數(shù)操作
這篇文章主要介紹了java 實(shí)現(xiàn)通過(guò) post 方式提交json參數(shù)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
Java8內(nèi)存模型PermGen Metaspace實(shí)例解析
這篇文章主要介紹了Java8內(nèi)存模型PermGen Metaspace實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03

