JAVA程式碼實現多級樹結構封裝物件(2018-09-26補充)
我們經常在程式碼裡會造一個樹結構物件,以方便前端使用。
以地區(區、鎮、村)為例
後臺一般對於樹結構物件在資料庫的結構是這樣的:
主鍵ID | 名字 | 父ID |
---|---|---|
ID | REGION_NAME | PARENT_ID |
121100 | 尼龍區 | 0 |
121100001 | 尼龍區鋼絲鎮 | 121100 |
121100001001 | 尼龍區鋼絲鎮螺絲村 | 121100001 |
主鍵ID | 名字 | 詞典表型別 |
---|---|---|
ID | REGION_NAME | DICT_TYPE |
121100 | 尼龍區 | XZQH |
121100001 | 尼龍區鋼絲鎮 | XZQH |
121100001001 | 尼龍區鋼絲鎮螺絲村 | XZQH |
231111 | 一般性支付 | ZFFS |
資料庫的結構如上,並沒有樹結構,需要根據DICT_TYPE為XZQH的記錄取出來,然後封裝成樹結構返回給前端,前端要的樹結構類似如下:
我的實現的邏輯是這樣的:
- 首先根據DICT_TYPE取出相關的地區記錄。
- 然後將區、鎮、村分別存到三個不同的map裡。
- 最後,巢狀遍歷三個map的key,區裡邊套鎮、鎮裡邊套村,封裝物件。(最重要的地方)。
具體步驟:
1、建立一個物件,用來規範樹結構。
public class FpzjXzdwArray implements Serializable { private String value; //對應資料庫的ID private String text; //對應資料庫的region_name private List<FpzjXzdwArray> children; //省略get/set方法了 }
2、第一步我就省略了。
3、第二步像我這種情況就是根據ID了,長度為6的放到區map裡,長度為9的放到鎮map裡,長度為12的放到村map裡。
Map<String,FpzjXzdwArray> quMap = new HashMap<String,FpzjXzdwArray>(); Map<String,FpzjXzdwArray> zhenMap = new HashMap<String,FpzjXzdwArray>(); Map<String,FpzjXzdwArray> cunMap = new HashMap<String,FpzjXzdwArray>();
4、巢狀遍歷三個map,首先縷縷我們的步驟。
以一個小例子為例,我們現在有一個大箱子、2箇中箱子(1紅、1藍)、6個紅藍小箱子(3紅、3藍)。要求是把大箱子裡裝上中箱子,中箱子裡要顏色對應裝進去小箱子。
**正確邏輯:**如果讓一個正常人來做,我們的邏輯都是一樣的,要先把顏色對應的小箱子放到中箱子裡以後,才會把中箱子放到大箱子裡,對嗎?
**錯誤邏輯:**如果你非要先把中箱子放到大箱子以後,再去拿對應顏色的小箱子放進中箱子裡去的話,這樣帶來的一個問題就是,你必須要先把大箱子開啟才可以完成這種事。所以這種邏輯就是錯誤的。
這個例子反映到程式碼裡也是一樣,如果你先往區物件裡塞進鎮物件集合,然後再去往鎮物件裡塞對應的村物件,就會像上邊的第二個步驟一樣,邏輯就錯了。我的程式碼如下:(最下邊還有別人分享給我的好方法,先貼上我的,瞬間感覺自己弱爆了)
for(String qu:quMap.keySet()){ //遍歷所有的區
for(String zhen:zhenMap.keySet()){ //遍歷所有的鎮
if(qu.equals(zhen.substring(0,6))){ //該區下找到該鎮
FpzjXzdwArray zhenXzdw = null;//定義這個是有必要的,這樣可以先完成對村物件塞到鎮物件裡,然後再完成鎮物件塞到區物件的步驟。
for(String cun:cunMap.keySet()){ //有區有鎮,然後再找下一級村
if(zhen.equals(cun.substring(0,9))){ //該鎮下找到村
zhenXzdw = zhenMap.get(zhen); //得到該鎮物件,
List<FpzjXzdwArray> xzdwArrayZhenList = zhenXzdw.getChildren(); //取出鎮物件下的村集合
if(xzdwArrayZhenList == null){
xzdwArrayZhenList = new ArrayList<>();
xzdwArrayZhenList.add(cunMap.get(cun));
zhenXzdw.setChildren(xzdwArrayZhenList); //將符合該鎮下的村塞到鎮物件裡
}else{
xzdwArrayZhenList.add(cunMap.get(cun));
zhenXzdw.setChildren(xzdwArrayZhenList); //將符合該鎮下的村塞到鎮物件裡
}
}
}
FpzjXzdwArray quXzdw = quMap.get(qu); //得到該區物件,
List<FpzjXzdwArray> xzdwArrayList = quXzdw.getChildren();//取出區物件下的鎮集合
if(xzdwArrayList == null){
xzdwArrayList = new ArrayList<>();
xzdwArrayList.add(zhenXzdw);
quXzdw.setChildren(xzdwArrayList); //將符合該區下的鎮物件塞到區物件裡
quMap.put(qu,quXzdw);
}else{
xzdwArrayList.add(zhenXzdw);
quXzdw.setChildren(xzdwArrayList);//將符合該區下的鎮物件塞到區物件裡
quMap.put(qu,quXzdw);
}
}
}
}
return quMap.values();
以上就是我寫的實現的邏輯,我還沒有用上遞迴,本質是這樣。
消耗的時間我也測試了,對我來說幾毫秒,最多7ms。
我的資料的數量是:
數量 | 區 | 鎮 | 村 |
---|---|---|---|
總數 | 8 | 66 | 674 |
遍歷的總次數:866674=? //其實也挺多的次數。。
分享一:
在我加的技術群裡吆喝了半天,有一位朋友分享他們的工具類,我感覺寫的很好了。他需要資料的結構是:
主鍵ID | 名字 | 父ID |
---|---|---|
ID | REGION_NAME | PARENT_ID |
121100 | 尼龍區 | 0 |
121100001 | 尼龍區鋼絲鎮 | 121100 |
121100001001 | 尼龍區鋼絲鎮螺絲村 | 121100001 |
public class TestTree{
private String id;
private String name;
private String pid;
private List<TestTree> testTrees;
//省略get/set方法
}
賦上他給我的兩個工具類:
工具類下載地址
使用的主要邏輯在TreeUtils類裡,在這裡邊我加了一個main方法,模擬了一個例子,大家可以參考。最後實現的結果如下圖:
他的這個工具類的好處是,利用了反射,只要你的資料結構符合上邊的id、pid、name這樣的資料,叫什麼名字都無所謂,不管多少層,都可以給弄出來。覺得這個特別好了。感謝@小太陽の !!
經過使用,發現,該方法,在很多的時候,特別慢。最後又找到一個好方法。
分享二:(2018-09-26補充)
發現了一個寫法超級牛掰的多級樹,我修改了一下,程式碼如下:
package znxd.tjzb.util;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import znxd.tjzb.model.region.RegionBeanTree;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by Administrator on 2018/9/26.
*/
public class TreeToolUtils {
private List<RegionBeanTree> rootList; //根節點物件存放到這裡
private List<RegionBeanTree> bodyList; //其他節點存放到這裡,可以包含根節點
public TreeToolUtils(List<RegionBeanTree> rootList, List<RegionBeanTree> bodyList) {
this.rootList = rootList;
this.bodyList = bodyList;
}
public List<RegionBeanTree> getTree(){ //呼叫的方法入口
if(bodyList != null && !bodyList.isEmpty()){
//宣告一個map,用來過濾已操作過的資料
Map<String,String> map = Maps.newHashMapWithExpectedSize(bodyList.size());
rootList.forEach(beanTree -> getChild(beanTree,map));
return rootList;
}
return null;
}
public void getChild(RegionBeanTree beanTree,Map<String,String> map){
List<RegionBeanTree> childList = Lists.newArrayList();
bodyList.stream()
.filter(c -> !map.containsKey(c.getCode()))
.filter(c ->c.getPid().equals(beanTree.getCode()))
.forEach(c ->{
map.put(c.getCode(),c.getPid());
getChild(c,map);
childList.add(c);
});
beanTree.setChildren(childList);
}
public static void main(String[] args){
RegionBeanTree beanTree1 = new RegionBeanTree();
beanTree1.setCode("540000");
beanTree1.setLabel("西藏省");
beanTree1.setPid("100000"); //最高節點
RegionBeanTree beanTree2 = new RegionBeanTree();
beanTree2.setCode("540100");
beanTree2.setLabel("拉薩市");
beanTree2.setPid("540000");
RegionBeanTree beanTree3 = new RegionBeanTree();
beanTree3.setCode("540300");
beanTree3.setLabel("昌都市");
beanTree3.setPid("540000");
RegionBeanTree beanTree4 = new RegionBeanTree();
beanTree4.setCode("540121");
beanTree4.setLabel("林周縣");
beanTree4.setPid("540100");
RegionBeanTree beanTree5 = new RegionBeanTree();
beanTree5.setCode("540121206");
beanTree5.setLabel("阿朗鄉");
beanTree5.setPid("540121");
RegionBeanTree beanTree6 = new RegionBeanTree();
List<RegionBeanTree> rootList = new ArrayList<>();
rootList.add(beanTree1);
List<RegionBeanTree> bodyList = new ArrayList<>();
bodyList.add(beanTree1);
bodyList.add(beanTree2);
bodyList.add(beanTree3);
bodyList.add(beanTree4);
bodyList.add(beanTree5);
TreeToolUtils utils = new TreeToolUtils(rootList,bodyList);
List<RegionBeanTree> result = utils.getTree();
result.get(0);
}
}
說實話,這種寫法我反正寫不出來,只能看懂,汗~,例子我放到最後了,大家可以下載下來直接執行即可。速度槓槓的。
造樹我覺得是挺重要的,挺常用的,如果有多級樹,我這種方式就不適用,所以我想找到一個可以封裝多級樹的好程式碼,希望有能看到,留言共享一下,我再把好的方法補充到這個文章裡。
相關推薦
JAVA程式碼實現多級樹結構封裝物件(2018-09-26補充)
我們經常在程式碼裡會造一個樹結構物件,以方便前端使用。 以地區(區、鎮、村)為例 後臺一般對於樹結構物件在資料庫的結構是這樣的: 主鍵ID 名字 父ID ID REGION_NAME PARENT_ID 121100 尼龍區 0 1211
JAVA代碼實現多級樹結構封裝對象
char parent set方法 get innodb 代碼 not static drop 樹結構在開發中經常遇到。例如:部門、菜單、員工架構等等。下面用部門作為例子構造部門結構樹 1、部門表:dept -- ----------------------------
java程式碼實現求樹的高度和節點數
求二叉樹的高度 public int getHeight(TreeNode node){ if(node == null){ return 0; } int i = getHeight(nod
智慧樹自動播放工具(2018/11/13更新)
描述:實現智慧樹教學視訊的自動播放,跳過彈題,自動下一節 基於前輩的更新版本 2018-10-07更新:修復自動播放按鈕點選消失的問題 var fa=$("body"); var btn=$("<li></li>");
【資料結構】二叉樹(順序儲存、鏈式儲存)的JAVA程式碼實現
二叉樹是一種非線性的資料結構。它是由n個有限元素的集合,該集合或者為空、或者由一個稱為根(root)的元素及兩顆不相交的、被分別稱為左子樹、右子樹的二叉樹組成。當集合為空時,稱該二叉樹為空二叉樹。在二叉樹中,一個元素也可以稱做一個結點。二叉樹是有序的,即若將其左右兩個子樹顛倒
演算法學習——中國大學MOOC-陳越、何欽銘-資料結構-起步能力自測題——java程式碼實現
自測-1 列印沙漏 (20 point(s)) 本題要求你寫個程式把給定的符號列印成沙漏的形狀。例如給定17個“*”,要求按下列格式列印 ***** *** * *** ***** 所謂“沙漏形狀”,是指每行輸出奇數個符號;各行符號中心對齊;相鄰兩行符號數差2;符號數先從大
java程式碼實現根據JSON檔案進行批量檔案重新命名或者改目錄結構
使用JAVA程式碼根據JSON檔案進行批量修改檔名以及路徑 某些網站視訊加密分割,首先去下載格式轉換工具,再用chrome F12開啟控制檯,找到json檔案進行檔案還原 json資料: {“message”:“hello”,“result”:[],“status”:200
資料結構4--佇列(java程式碼實現佇列的鏈式儲存)
1.什麼是佇列? 佇列也叫隊,時允許在一段進行擦汗如另一端進行刪除的運算受限的線性表。區別佇列和棧:棧時先進後出,佇列時先進先出。 &nbs
資料結構2--線性表(java程式碼實現線性表的鏈式儲存)
1.鏈式儲存 2.分析 每個節點為一個物件,該物件包含資料域和指標域 整條單鏈表為一個物件,他和節點物件進行組合。 3.
資料結構1--線性表(java程式碼實現線性表的順序儲存)
1.資料結構的概念 資料:資訊載體,計算機處理的物件的總稱 資料元素:也稱結點,組成資料的基本單位 資料項:資料項是資料的最小單位 &n
買什麼資料結構與演算法,這裡有:動態圖解十大經典排序演算法(含JAVA程式碼實現)
上篇的動圖資料結構反響不錯,這次來個動圖排序演算法大全。資料結構與演算法,齊了。 幾張動態圖捋清Java常用資料結構及其設計原理 本文將採取動態圖+文字描述+正確的java程式碼實現來講解以下十大排序演算法: 氣泡排序 選擇排序 插入排序 希爾排序
【資料結構與演算法】回溯法解決N皇后問題,java程式碼實現
N皇后問題 問題描述 在8×8格的國際象棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法,這稱為八皇后問題。 延伸一下,便為N皇后問題。 核心思想 解決N皇后問題有兩個關鍵點。一是如何進行放置棋子,二是如何驗證棋子是否符合
【資料結構與演算法】貪心演算法解決揹包問題。java程式碼實現
揹包問題(貪心演算法) 貪心演算法思想 簡單的說,就是將大問題轉化為最優子問題,例如本題所要求的,揹包容量有限,要想使物品的總價值最高,那麼,我們必須儘可能的選擇權重高的(即單位價值更高)的物品進行裝載。 在揹包問題中,物品是可拆的,即可以分成任意部分進行裝載,而最終實現的目標是
關於資料結構演算法中的比較排序(一)(附Java程式碼實現)
現在已經是10月份,秋招正在進行,不知道是不是有的人會和我一樣正在瘋狂的複習起資料結構,在這裡我將就常見的幾種比較排序做一些簡單的解析,同時附上具體的程式碼實現。 1.氣泡排序 氣泡排序通常是我們最先接觸道的比較排序的一種,具體排序步驟如下: 1.比較相鄰的元
【資料結構與演算法】之單鏈表、雙鏈表、迴圈連結串列的基本介紹及其Java程式碼實現---第三篇
一、連結串列的基本介紹 連結串列的定義:連結串列是一種遞迴的資料結構,它或者為空(null),或者是指向一個結點(node)的引用,該結點含有一個泛型的元素和一個指向另一條連結串列的引用。----Algorithms Fourth Edition 常見的連結串
樹的層次遍歷(Java程式碼實現)
與樹的前中後序遍歷的DFS思想不同,層次遍歷用到的是BFS思想。一般DFS用遞迴去實現(也可以用棧實現),BFS需要用佇列去實現。 層次遍歷的步驟是: 1.對於不為空的結點,先把該結點加入到佇列中 2.從隊中拿出結點,如果該結點的左右結點不為空,就分別把左右結點加入到佇列
用Java實現簡單樹結構
Node實體: package treeTest; import java.io.Serializable; import java.util.List; /** * ClassName: No
劍指Offer 面試題34:二叉樹中和為某一值的路徑 Java程式碼實現
題目:輸入一棵二叉樹和整數,打印出二叉樹中節點值得和為輸入整數的所有路徑。從樹的根節點開始往下一直到葉節點所經過的節點形成一條路徑。 解題思路:路徑從根節點開始,應該用類似於前序遍歷的方式訪問樹節點。
紅黑樹Red-Black tree初步詳解(Java程式碼實現)
紅黑樹Red-Blacktree初步詳解 本部落格的參考資料: 演算法導論 http://blog.csdn.net/v_july_v/article/details/6105630 http://www.cnblogs.com/skywang12345/p/3624343
【資料結構】圖(最短路徑Dijkstra演算法)的JAVA程式碼實現
最短路徑的概念最短路徑的問題是比較典型的應用問題。在圖中,確定了起始點和終點之後,一般情況下都可以有很多條路徑來連線兩者。而邊或弧的權值最小的那一條路徑就稱為兩點之間的最短路徑,路徑上的第一個頂點為源點,最後一個頂點為終點。圖的最短路徑的演算法有很多,本文主要介紹狄克斯特拉(