java 转化为树工具类

Java 树状结构转化工具类

1:使用场景:菜单结构数(n级别)

2:数据库存储的往往的是一条条的数据,通过id,查询数据库的父类id进行获取子类数据,然后进行组装数据,数据曾经可能很多。

往往的解决思路是通过递归进行查询,递归中可能会写sql查询,效率极低。有需要的可以了解一下递归的时间复杂度和空间复杂度。

3:本工具类的优点在于以空间换时间的思路。通过查询出所需要的数据,将数据进行内存中处理,使用一层for结构,进行遍历循环,获取子类并进行组装数据

具体可以看代码

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

public class TreeUtils<T> {
    private final Map<Object, T> nodeMap = new HashMap<>();
    private final List<T> root = new ArrayList<>();
    private final List<T> baseRoot = new ArrayList<>();
    private String childParamName = null;
    private String parentParamName = null;
    private String listParamName = null;
    private final List<T> listData;
    private final Class<?> aClass;
    private Method methodGet;
    private Method methodSet;

    /**
     * 初始化数据
     * @param nodes
     */
    public TreeUtils(List<T> nodes) {
        this.listData = nodes;
        aClass = nodes.get(0).getClass();
        setBase();
        listData.forEach(res -> nodeMap.put(getVal(res, parentParamName), res));
    }

    /**
     * 转化为树,默认返回跟节点
     */
    public List<T> tree() {
        listData.forEach(one -> {
            T childData = nodeMap.get(getVal(one, childParamName));
            if (childData != null) {
                setVal(childData, one);
            } else {
                baseRoot.add(one);
            }
        });
        return getBaseRoot();
    }

    /**
     * 转化为树,默认返回节点为base的节点树
     */
    public List<T> tree(Object base) {
        if (base == null) {
            return tree();
        }
        listData.forEach(one -> {
            T childData = nodeMap.get(getVal(one, childParamName));
            if (childData != null) {
                setVal(childData, one);
            }
            if (base.toString().equals(String.valueOf(getVal(one, parentParamName)))) {
                root.add(one);
            }
        });
        return getRoot();
    }
    private void setBase() {
        Field[] tableDoris = this.aClass.getDeclaredFields();
        for (Field doris : tableDoris) {
            TreeUtil annotation = doris.getAnnotation(TreeUtil.class);
            if (annotation != null) {
                if (TreeType.id.name().equals(annotation.value().toString())) {
                    parentParamName = doris.getName();
                } else if (TreeType.parentId.name().equals(annotation.value().toString())) {
                    childParamName = doris.getName();
                } else if (TreeType.childList.name().equals(annotation.value().toString())) {
                    listParamName = doris.getName();
                }
            }
        }
        try {
            this.methodGet = aClass.getMethod("get" + getMethodName(listParamName));
            this.methodGet.setAccessible(true);

            this.methodSet = aClass.getMethod("set" + getMethodName(listParamName), List.class);
            this.methodSet.setAccessible(true);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    private Object getVal(T t, String name) {
        // 获取单个属性
        try {
            Field field = aClass.getDeclaredField(name);
            field.setAccessible(true);
            return field.get(t);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @SuppressWarnings("unchecked")
    private void setVal(T t, T child) {
        // 获取单个属性
        try {
            List<T> childData = null;
            Object obj = methodGet.invoke(t);
            if (obj instanceof List<?>) {
                childData = (List<T>) obj;
            }
            if (childData == null) {
                childData = new ArrayList<>();
            }
            childData.add(child);
            methodSet.invoke(t, childData);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    private List<T> getBaseRoot() {
        return baseRoot;
    }

    private List<T> getRoot() {
        return root;
    }

    private static String getMethodName(String fieldName) {
        byte[] items = fieldName.getBytes();
        items[0] = (byte) ((char) items[0] - 'a' + 'A');
        return new String(items);
    }
}


@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface TreeUtil {
    TreeType value();
}

enum TreeType {
    //标识为id,
    id,
    //标识为父类id字段
    parentId,
    //表示为结果存储对象
    childList
}
View Code

 


 


使用

加入注解

import lombok.Data;

import java.util.List;

/**
 * 视图实体类
 *
 * @author Chill
 */
@Data
public class TestTree {
    /**
     * 主键ID
     */
    @TreeUtil(value = TreeType.id)
    private Long id;

    /**
     * 父节点ID
     */
    @TreeUtil(value =TreeType.parentId)
    private Long parentId;
    /**
     * 子孙节点
     */
    @TreeUtil(value = TreeType.childList)
    private List<TestTree> children;

}
View Code

 


测试

public static void main(String[] args) {
        List<TestTree> list1 = new ArrayList<>();
        for (long i = 0; i < 10; i++) {
            TestTree menuVO = new TestTree();
            menuVO.setId(i);
            menuVO.setParentId(i-1);
            list1.add(menuVO);
        }
        System.out.println( new TreeUtils<>(list1).tree());
    }
View Code

 


效果

[TestTree(id=0, parentId=-1, children=[TestTree(id=1, parentId=0, children=[TestTree(id=2, parentId=1, children=[TestTree(id=3, parentId=2, children=[TestTree(id=4, parentId=3, children=[TestTree(id=5, parentId=4, children=[TestTree(id=6, parentId=5, children=[TestTree(id=7, parentId=6, children=[TestTree(id=8, parentId=7, children=[TestTree(id=9, parentId=8, children=null)])])])])])])])])])]



 

 

posted @ 2023-07-27 11:33  沐海风  阅读(91)  评论(0编辑  收藏  举报