前端
id: 1, label: '一級 1', children: id: 4, label: '二級 1-1', children: id: 9, label: '三級 1-1-1', children: ...
一、首先咱們須要獲取到全部的節點,新建一個集合result來保存全部頂級節點,也就是parentId爲空的或指定值。數據庫
二、而後咱們須要找出二級節點存入到頂級節點的childList中,找到三級節點存入到二級節點的childList中,依次類推,最後將result返回。數據結構
@Data public class Evaluation { private String id; private String label; private String parentId; private List<Evaluation> childList; }
public class EvaluationService { private EvaluationDao evaluationDao; public List<Evaluation> getEvaluations() { // 查出全部指標 List<Evaluation> all = evaluationDao.findAll(); // 把全部的數據都放到map中 Map<String, Evaluation> treeMap = new HashMap<>(); for (int i = 0; i < all.size() && !all.isEmpty(); i++) { // 元素的id爲鍵,元素自己爲值 treeMap.put(all.get(i).getId(), all.get(i)); } // 將全部頂層節點存入result中 List<Evaluation> result = new ArrayList<>(); // 遍歷map獲得頂層節點或者遊離節點 for (int i = 0; i < all.size(); i++) { if (!treeMap.containsKey(all.get(i).getParentId())) { result.add(all.get(i)); } } // 遍歷數據,將對象放入父級節點的childList屬性中 for (int i = 0; i < all.size() && !all.isEmpty(); i++) { Evaluation Evaluation = treeMap.get(all.get(i).getParentId()); if (Evaluation != null) { // 有父節點,校驗父節點下childList是否存在,而後將子節點放入 if (Evaluation.getChildList() == null) { Evaluation.setChildList(new ArrayList<>()); } // 添加到父節點的ChildList集合下 Evaluation.getChildList().add(all.get(i)); } } return result; } }
若是項目中使用的很少的話,這樣就能夠了。實現方式能夠有不少種,用上邊的方式的好處在於免去了屢次到數據庫查詢的操做,並且能夠靈活封裝多層級數據,二層、三層、五層等等均可以。工具
爲了實現代碼的複用,咱們能夠將上方代碼封裝成工具類。lua
寫這個接口類主要是爲了下面的工具類,定義泛型T的類型 spa
public interface DataTree<T> { public String getId(); public String getParentId(); public void setChildList(List<T> childList); public List<T> getChildList(); }
如下的泛型T就是接收數據的實體類,要繼承上面數據接口類設計
public class TreeUtils { //獲取頂層節點 public static <T extends DataTree<T>> List<T> getTreeList(String topId, List<T> entityList) { List<T> resultList = new ArrayList<>(); Map<Object, T> treeMap = new HashMap<>(); T itemTree; for (int i = 0; i < entityList.size() && !entityList.isEmpty(); i++) { itemTree = entityList.get(i); //把全部的數據放到treeMap中,id爲key treeMap.put(itemTree.getId(), itemTree); //把頂層節點放到集合resultList中 if (topId.equals(itemTree.getParentId()) || itemTree.getParentId() == null) { resultList.add(itemTree); } } //循環數據,把數據放到上一級的childen屬性中 for (int i = 0; i < entityList.size() && !entityList.isEmpty(); i++) { itemTree = entityList.get(i); T data = treeMap.get(itemTree.getParentId()); // 不等於null,也就意味着有父節點 if (data != null) { if (data.getChildList() == null) { data.setChildList(new ArrayList<>()); } //把子節點 放到父節點childList當中 data.getChildList().add(itemTree); //把放好的數據放回map當中 treeMap.put(itemTree.getParentId(), data); } } return resultList; } }
一、實體類:code
設計實體類,實現以前定義好的DataTree接口對象
@Data public class Evaluation implements DataTree<Evaluation> { private String id; private String label; private String parentId; private List<Evaluation> childList; }
二、調用TreeUtils,傳入數據和頂層節點id,便可獲取到所須要的數據結構。blog
public class Test { private EvaluationDao evaluationDao; public List<Evaluation> getEvaluations() { // 接收在數據庫中查詢到的數據 List<Evaluation> data = evaluationDao.findAll(); // 調用工具類,第一個參數是默認傳入的頂級id,和查詢出來的數據 return TreeUtils.getTreeList("0", data); } }