粘贴即用,欢迎使用
树形数据工具类(泛型+反射->所有类别可用)
package com.record.util;
import com.record.auth.entity.SysMenu;
import com.sun.xml.internal.messaging.saaj.soap.impl.TreeException;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 公共树形工具转化类
* 详细用法以下有main方法示例
* 实体类中若需要看打印则需要tostring方法
* @author 丁建荣
* @param <T>
*/
@Component
public class TreeUtil<T> {
/**
* 公共转化
* @param list -- 传入的实体集合
* @param menuEntityName -- 在实体类中id的名称
* @param pMenuEntityName -- 在实体类中父id的名称
* @param childEntityName -- 在实体类中子集合的名称
* @param rootValue -- (根)第一节点的参考值
* @return
*/
public List<T> start(List<T> list,String menuEntityName,String pMenuEntityName,String childEntityName,String rootValue){
//参数判空
try {
if(ProcessingCheck.isEmpty(list)){
throw new TreeUtilException("传入集合不能为空");
}
if(ProcessingCheck.isEmpty(menuEntityName)){
throw new TreeUtilException("标识属性名称不能为空");
}
if(ProcessingCheck.isEmpty(pMenuEntityName)){
throw new TreeUtilException("父级标识属性名称不能为空");
}
if(ProcessingCheck.isEmpty(childEntityName)){
throw new TreeUtilException("子集属性名称不能为空");
}
if(ProcessingCheck.isEmpty(rootValue)){
throw new TreeUtilException("根节点值不能为空");
}
} catch (TreeUtilException e) {
e.printStackTrace();
return null;
}
//获取根节点集合
List<T> pList = list.stream().filter(a -> rootValue.equals(ReflexOperation.getFieldValueByName(pMenuEntityName, a))).collect(Collectors.toList());
//移除根节点集合
list.removeAll(pList);
//调用递归返回最终结果
return changeTree(pList,list,menuEntityName,pMenuEntityName,childEntityName);
}
/**
* 解析属性结构数据生成树形集合
*/
public List<T> changeTree(List<T> pList,List<T> list,String menuEntityName,String pMenuEntityName,String childEntityName){
for(int i=0;i<pList.size();i++) {
T p = pList.get(i);
//初始化即将存入实体类子集的集合数据
List<T> childrenList = new ArrayList<>();
//获取字段属性值
Field filed = ReflexOperation.getFiled(childEntityName, p);
//设置允许访问对象
filed.setAccessible(true);
//遍历插入
List<T> collect = list.stream().filter(c ->
null!=ReflexOperation.getFieldValueByName(menuEntityName, p)&&null!=ReflexOperation.getFieldValueByName(pMenuEntityName, c)&&
ReflexOperation.getFieldValueByName(menuEntityName, p).equals(ReflexOperation.getFieldValueByName(pMenuEntityName, c))).collect(Collectors.toList());
collect.stream().forEach(d -> {
//初始化执行状态
boolean statu=true;
if(null != list && list.size() > 0){
statu=true;
}else{
statu=false;
}
//去除已经被使用的实体
list.remove(d);
if (statu) {
//递归调用形成子集实体的子集集合
d = this.doChangeTree(d, list, menuEntityName, pMenuEntityName, childEntityName);
//添加对应子集实体
childrenList.add(d);
}
});
//将子集集合插入父实体中
try {
filed.set(p, childrenList);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//设置不允许对象访问
filed.setAccessible(false);
}
return pList;
}
/**
* 递归调用方法
*/
public T doChangeTree(T t,List<T> list,String menuEntityName,String pMenuEntityName,String childEntityName){
//初始化即将存入实体类子集的集合数据
List<T> childrenList=new ArrayList<>();
//获取字段属性值
Field filed = ReflexOperation.getFiled(childEntityName, t);
//设置允许访问对象
filed.setAccessible(true);
List<T> collect = list.stream().filter(a ->
null!=ReflexOperation.getFieldValueByName(menuEntityName, t)&&null!=ReflexOperation.getFieldValueByName(pMenuEntityName, a)&&
ReflexOperation.getFieldValueByName(menuEntityName, t).equals(ReflexOperation.getFieldValueByName(pMenuEntityName, a))).collect(Collectors.toList());
collect.stream().forEach(b->{
//初始化执行状态
boolean statu=true;
if(null != list && list.size() > 0){
statu=true;
}else{
statu=false;
}
//去除已经被使用的实体
list.remove(b);
if(statu){
//递归调用形成子集实体的子集集合
b=this.doChangeTree(b,list,menuEntityName,pMenuEntityName,childEntityName);
//添加对应子集实体
childrenList.add(b);
}
});
//将子集集合插入父实体中
try {
filed.set(t,childrenList);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//设置不允许对象访问
filed.setAccessible(false);
return t;
}
/**
* 设定内部类-启动反射机制
*/
static class ReflexOperation{
/**
* @desc 获取属性名数组
* @param o
* @return
*/
public String[] getFiledName(Object o) {
Field[] fields = o.getClass().getDeclaredFields();
String[] fieldNames = new String[fields.length];
for (int i = 0; i < fields.length; i++) {
fieldNames[i] = fields[i].getName();
}
return fieldNames;
}
/**
* @desc 根据属性名获取属性值
* @param fieldName
* @param o
* @return
*/
public static Object getFieldValueByName(String fieldName, Object o) {
try {
String firstLetter = fieldName.substring(0, 1).toUpperCase();
String getter = "get" + firstLetter + fieldName.substring(1);
Method method = o.getClass().getMethod(getter, new Class[] {});
Object value = method.invoke(o, new Object[] {});
return value;
}catch (NoSuchMethodException noSuchMethodException){
throw new TreeException("参数名: "+fieldName+" 不存在!");
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @desc 获取属性的数据类型
* @param fieldName
* @param o
* @return
*/
public static Field getFiled(String fieldName, Object o) {
Field[] fields = o.getClass().getDeclaredFields();
for (Field field : fields) {
if (Objects.equals(fieldName, field.getName())) {
return field;
}
}
throw new TreeException("参数名: "+fieldName+" 不存在!");
}
}
/**
* 自定义异常类
*/
static class TreeUtilException extends Exception{
public TreeUtilException(){
}
//带有详细信息的构造器,信息存储在message中
public TreeUtilException(String message) {
super(message);
}
}
/**
* 条件类
*/
static class ProcessingCheck{
static boolean isEmpty(Object object){
if(null==object||"".equals(String.valueOf(object))){
return true;
}
return false;
}
}
/**
* 测试使用
* @param args
*/
public static void main(String[] args) {
List<SysMenu> list = new ArrayList<>();
SysMenu sysMenu = new SysMenu();
sysMenu.setMenuId("111");
sysMenu.setPMenuId("-1");
list.add(sysMenu);
SysMenu sysMenu1 = new SysMenu();
sysMenu1.setMenuId("222");
sysMenu1.setPMenuId("-1");
list.add(sysMenu1);
SysMenu sysMenu2 = new SysMenu();
sysMenu2.setMenuId("1110");
sysMenu2.setPMenuId("111");
list.add(sysMenu2);
SysMenu sysMenu3 = new SysMenu();
sysMenu3.setMenuId("2220");
sysMenu3.setPMenuId("222");
list.add(sysMenu3);
SysMenu sysMenu4 = new SysMenu();
sysMenu4.setMenuId("11101");
sysMenu4.setPMenuId("1110");
list.add(sysMenu4);
SysMenu sysMenu5 = new SysMenu();
sysMenu5.setMenuId("111010");
sysMenu5.setPMenuId("11101");
list.add(sysMenu5);
SysMenu sysMenu6 = new SysMenu();
sysMenu6.setMenuId(null);
sysMenu6.setPMenuId(null);
list.add(sysMenu6);
TreeUtil<SysMenu> sysMenuTreeUtil = new TreeUtil<>();
System.out.println(sysMenuTreeUtil.start(list,"menuId","pMenuId","childrenMnenus","-1"));
}
}