java構建樹形列表(帶children屬性)- 樹形結構工具類
阿新 • • 發佈:2022-04-02
package com.xie.util; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.reflect.FieldUtils; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; /** * @Description java構建樹形列表(帶children屬性) * 樹形表格工具類 * @Date 2022-03-30 15:16 * @Author xie */ public class TreeTableUtil { /** * * @param originalList 原始的list資料 * @param idFieldName 唯一標識的欄位名稱(主鍵) * @param pidFieldName 父節點標識的欄位名稱 * @param childrenFieldName 子節點列表標識的欄位名稱 * @return java.util.List<T> 樹結構列表 */ public static <T> List<T> list2TreeList(List<T> originalList, String idFieldName, String pidFieldName, String childrenFieldName) { // 獲取根節點,就是找出父節點為空的物件 List<T> rootNodeList = new ArrayList<>(); for (T t : originalList) { String parentId = null; try { parentId = BeanUtils.getProperty(t, parentId); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { e.printStackTrace(); } if (StringUtils.isBlank(parentId)) { rootNodeList.add(0, t); } } // 將根節點從原始list移除,減少下次處理資料 originalList.removeAll(rootNodeList); // 遞迴封裝樹 try { packTree(rootNodeList, originalList, idFieldName, pidFieldName, childrenFieldName); } catch (Exception e) { e.printStackTrace(); } return rootNodeList; } /** * 封裝樹(向下遞迴) * * @param parentNodeList 要封裝為樹的父節點物件集合 * @param originalList 原始list資料 * @param idFieldName 作為唯一標示的欄位名稱 * @param pidFieldName 父節點標識欄位名 * @param childrenFieldName 子節點(列表)標識欄位名 */ private static <T> void packTree(List<T> parentNodeList, List<T> originalList, String idFieldName, String pidFieldName, String childrenFieldName) throws Exception { for (T parentNode : parentNodeList) { // 找到當前父節點的子節點列表 List<T> children = packChildren(parentNode, originalList, idFieldName, pidFieldName, childrenFieldName); if (children.isEmpty()) { continue; } // 將當前父節點的子節點從原始list移除,減少下次處理資料 originalList.removeAll(children); // 開始下次遞迴 packTree(children, originalList, idFieldName, pidFieldName, childrenFieldName); } } /** * 封裝子物件 * * @param parentNode 父節點物件 * @param originalList 原始list資料 * @param keyName 作為唯一標示的欄位名稱 * @param pidFieldName 父節點標識欄位名 * @param childrenFieldName 子節點(列表)標識欄位名 */ private static <T> List<T> packChildren(T parentNode, List<T> originalList, String keyName, String pidFieldName, String childrenFieldName) throws Exception { // 找到當前父節點下的子節點列表 List<T> childNodeList = new ArrayList<>(); String parentId = BeanUtils.getProperty(parentNode, keyName); for (T t : originalList) { String childNodeParentId = BeanUtils.getProperty(t, pidFieldName); if (parentId.equals(childNodeParentId)) { childNodeList.add(t); } } // 將當前父節點下的子節點列表寫入到當前父節點下(給子節點列表欄位賦值) if (!childNodeList.isEmpty()) { FieldUtils.writeDeclaredField(parentNode, childrenFieldName, childNodeList, true); } return childNodeList; } }