天天看點

通過遞歸構造樹背景實體結構代碼

遞歸構樹

  • 背景
  • 實體結構
  • 代碼

背景

構造一棵樹,再通過json傳回給前端展示是我們經常需要遇到的功能。在這裡總結一下通過遞歸功能構造樹,結合着stream,将代碼變得簡潔易懂。

實體結構

通常的實體類型樹結構,為List< List<…> >,最外邊為root節點,裡邊為子子孫孫節點。其中還需要有一個關聯關系,子節點可以通過parentId關聯父節點。實體類例子如下:

這是一個類名為SlogPolicy的樹結構,其中主要用到的屬性如下:

通過遞歸構造樹背景實體結構代碼

所屬層級和路徑如有需要可以加上,并不影響樹的構造

通過遞歸構造樹背景實體結構代碼
通過遞歸構造樹背景實體結構代碼

代碼

因為比較簡單、代碼就直接貼圖了。但是思路會在下方指出

通過遞歸構造樹背景實體結構代碼

上圖有三步:

  1. 從資料庫中擷取到所有需要展示的節點,相當于直接緩存到記憶體中;
  2. 通過filter方法過濾出父節點,依據為parentId為0;
  3. 通過peek方法在每一個父節點下set子節點。

之後進入擷取子節點的遞歸方法getChildren(),如下:

參數說明:第一個參數就是目前父節點、第二個參數為上述步驟1查詢出的資料

通過遞歸構造樹背景實體結構代碼
  1. 通過stream對所有資料進行操作
  2. 通過filter方法過濾出所屬父節點,依據為子節點的parentId為父節點的id;
  3. 通過peek方法在每一個子節點下再set孫節點。如有需要也可以通過sorted方法對生成的清單排序
遞歸出口:可以想到,當子節點下再找不到下一級的子節點了,那麼這個root節點下的遞歸構造就完成了,便可回溯。也就是通過filter方法過濾出的資料為空了。

上訴步驟完成後,樹結構就構造完成。可以看到通過stream流方式很友善。

這樣的方法還可以想到優化的點,因為每次要把所有查到的資料作為參數代入到遞歸方法中,之後通過stream處理。資料量大的情況下會耗費一定的性能。是以也可以通過:

1、不一次性查詢到所有資料緩存到記憶體中,而是先查到所有父節點資料,再在遞歸過程中查詢到其下的子節點資料。(這樣是會照成請求資料庫I/O次數較多)。

2、可以将已經set的資料進行清理,這樣資料量會逐級遞減。

上訴stream流中使用到了peek方法,說明一下與map的差別:

主要差別為:peek為消費型接口,調用peek方法後, 流還在。

map方法是函數型接口。調用map方法後,流已經被消費。

peek對一個對象進行操作的時候,對象不變,但是可以改變對象裡面的值

map方法接收一個Function作為入參. Function是有傳回值的, 這就表示map對Stream中的元素的操作結果都會傳回到Stream中去

四種函數式接口:

通過遞歸構造樹背景實體結構代碼