List转树工具类

传入一个对象及指定字段

循环

import java.util.ArrayList;
import java.util.List;

public class TreeUtils {

    /**
     * 将 List 集合转为树状结构
     * @param nodes 待转换的 List 集合,其中对象必须包含指定的父级字段和节点ID字段
     * @param parentIdField 父级字段名称
     * @param idField 节点ID字段名称
     * @param <T> 对象类型
     * @return 转换后的树状结构
     */
    public static <T> List<T> listToTree(List<T> nodes, String parentIdField, String idField) throws NoSuchFieldException, IllegalAccessException {
        List<T> treeNodes = new ArrayList<>();
        for (T node : nodes) {
            Object parentIdValue = getFieldValue(node, parentIdField);
            int parentId = Integer.parseInt(parentIdValue.toString());
            if (parentId == 0) {
                //父ID为0为根节点, 直接加入列表中
                treeNodes.add(node);
                continue;
            }
            // 将节点加入对应的父节点中
            for (T parent : nodes) {
                Object idValue = getFieldValue(parent, idField);
                int id = Integer.parseInt(idValue.toString());
                if (id == parentId) {
                    Object children = getFieldValue(parent, "children");
                    if (children == null){
                        setFieldValue(parent,"children",new ArrayList());
                    }
                    ((List<T>)getFieldValue(parent, "children")).add(node);
                }
            }
        }
        return treeNodes;
    }

    /**
     * 反射获取对象的属性值
     * @param obj 目标对象
     * @param fieldName 属性名
     * @return 属性值
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    private static Object getFieldValue(Object obj, String fieldName) throws NoSuchFieldException, IllegalAccessException {
        Class<?> clazz = obj.getClass();
        Field field = clazz.getDeclaredField(fieldName);
        field.setAccessible(true);
        return field.get(obj);
    }

    /**
     * 反射设置对象的属性值
     * @param obj 目标对象
     * @param fieldName 属性名
     * @param value 属性值
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    private static void setFieldValue(Object obj, String fieldName, Object value) {
        try {
            Class<?> clazz = obj.getClass();
            java.lang.reflect.Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(obj, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用时调用listToTree方法,并传入待转换的List集合,父级字段名称、节点ID字段名称。示例代码如下:

public class ExampleNode {
    private int parentId;
    private int id;
    private String name;
    private List<ExampleNode> children = new ArrayList<>();
    // 其他属性和方法
}

List<ExampleNode> nodes = new ArrayList<>();
// 填充节点数据

List<ExampleNode> tree = TreeUtils.listToTree(nodes, "parentId", "id");

递归实现

import java.util.ArrayList;
import java.util.List;

public class TreeUtils {
    public static <T> List<T> listToTree(List<T> nodes, String parentIdField, String idField) {
        List<T> treeNodes = new ArrayList<>();
        for (T node : nodes) {
            Object parentIdValue = getFieldValue(node, parentIdField);
            int parentId = Integer.parseInt(parentIdValue.toString());
            if (parentId == 0) {
                // 父ID为0为根节点,直接加入列表中
                treeNodes.add(node);
                // 递归处理子节点
                setChildren(node, nodes, parentIdField, idField);
            }
        }
        return treeNodes;
    }

    private static <T> void setChildren(T parent, List<T> nodes, String parentIdField, String idField) {
        List<T> children = new ArrayList<>();
        for (T node : nodes) {
            Object parentIdValue = getFieldValue(node, parentIdField);
            int parentId = Integer.parseInt(parentIdValue.toString());
            Object idValue = getFieldValue(parent, idField);
            int id = Integer.parseInt(idValue.toString());
            if (parentId == id) {
                // 将节点加入对应的父节点中
                children.add(node);
                // 递归处理子节点
                setChildren(node, nodes, parentIdField, idField);
            }
        }
        if (!children.isEmpty()) {
            setFieldValue(parent, "children", children);
        }
    }

    /**
     * 反射获取对象的属性值
     * @param obj 目标对象
     * @param fieldName 属性名
     * @return 属性值
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    private static Object getFieldValue(Object obj, String fieldName) {
        try {
            Class<?> clazz = obj.getClass();
            java.lang.reflect.Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 反射设置对象的属性值
     * @param obj 目标对象
     * @param fieldName 属性名
     * @param value 属性值
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    private static void setFieldValue(Object obj, String fieldName, Object value) {
        try {
            Class<?> clazz = obj.getClass();
            java.lang.reflect.Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(obj, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

传入的对象是List<Map<String,Object>>结构

递归

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class TreeUtils {
    public static List<Map<String, Object>> listToTree(List<Map<String, Object>> nodes, String parentIdField, String idField) {
        List<Map<String, Object>> treeNodes = new ArrayList<>();
        for (Map<String, Object> node : nodes) {
            Object parentIdValue = node.get(parentIdField);
            int parentId = Integer.parseInt(parentIdValue.toString());
            if (parentId == 0) {
                // 父ID为0为根节点,直接加入列表中
                treeNodes.add(node);
                // 递归处理子节点
                setChildren(node, nodes, parentIdField, idField);
            }
        }
        return treeNodes;
    }

    private static void setChildren(Map<String, Object> parent, List<Map<String, Object>> nodes, String parentIdField, String idField) {
        List<Map<String, Object>> children = new ArrayList<>();
        for (Map<String, Object> node : nodes) {
            Object parentIdValue = node.get(parentIdField);
            int parentId = Integer.parseInt(parentIdValue.toString());
            Object idValue = parent.get(idField);
            int id = Integer.parseInt(idValue.toString());
            if (parentId == id) {
                // 将节点加入对应的父节点中
                children.add(node);
                // 递归处理子节点
                setChildren(node, nodes, parentIdField, idField);
            }
        }
        if (!children.isEmpty()) {
            parent.put("children", children);
        }
    }
}

List<Map<String, Object>> nodes = new ArrayList<>();
// 填充节点数据

List<Map<String, Object>> treeNodes = TreeUtils.listToTree(nodes, "parentId", "id");

循环

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class TreeUtils {
    public static List<Map<String, Object>> listToTree(List<Map<String, Object>> nodes, String parentIdField, String idField) {
        List<Map<String, Object>> treeNodes = new ArrayList<>();
        for (Map<String, Object> node : nodes) {
            if (node.get(parentIdField).toString().equals("0")) {
                // 父ID为0为根节点,直接加入列表中
                treeNodes.add(node);
            }
            for (Map<String, Object> parentNode : nodes) {
                if (parentNode.get(idField).equals(node.get(parentIdField))) {
                    List<Map<String, Object>> children = (List<Map<String, Object>>) parentNode.get("children");
                    if (children == null) {
                        children = new ArrayList<>();
                        parentNode.put("children", children);
                    }
                    children.add(node);
                    break;
                }
            }
        }
        return treeNodes;
    }
}

List<Map<String, Object>> nodes = new ArrayList<>();
// 填充节点数据

List<Map<String, Object>> treeNodes = TreeUtils.listToTree(nodes, "parentId", "id");

循环

public class TreeUtils {

    /**
     * 将 List 转为树形结构
     *
     * @param list     List 数据
     * @param idFieldName ID 字段名
     * @param parentIdFieldName 父 ID 字段名
     * @return 返回树形结构数据
     */
    public static List<Map<String, Object>> listToTree(List<Map<String, Object>> list, String idFieldName, String parentIdFieldName) {
        List<Map<String, Object>> treeList = new ArrayList<>();
        
        // 将 list 转换为以 id 为 key 的 map
        Map<Object, Map<String, Object>> map = new HashMap<>();
        for (Map<String, Object> mapItem : list) {
            Object id = mapItem.get(idFieldName);
            map.put(id, mapItem);
        }

        for (Map<String, Object> mapItem : list) {
            Object parentId = mapItem.get(parentIdFieldName);
            if (parentId == null) {
                treeList.add(mapItem);
            } else {
                Map<String, Object> parent = map.get(parentId);
                if (parent != null) {
                    List<Map<String, Object>> children = (List<Map<String, Object>>) parent.get("children");
                    if (children == null) {
                        children = new ArrayList<>();
                        parent.put("children", children);
                    }
                    children.add(mapItem);
                }
            }
        }
        return treeList;
    }

}

使用时,可以按照以下方式调用:

List<Map<String, Object>> list = new ArrayList<>();
// 添加 List 数据

List<Map<String, Object>> treeList = TreeUtils.listToTree(list, "id", "parentId");
// 将 List 转为树形结构数据

其中,list 参数为需要转换的 List 对象,idFieldName 参数为 id 字段名,parentIdFieldName 参数为父 id 字段名,可以根据实际业务场景进行具体实现。
值得注意的是,在工具类中,需要将待转换的 List 对象中的数据转换为以 id 为 key 的 Map,以便在后续的处理中能够快速查找对应节点的父节点,并设置其子节点。同时,在转换过程中,需要在 Map 中保存每个节点的子节点列表信息。

测试

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class TreeInfoDTO implements Serializable {

    private static final long serialVersionUID = 6609328309422561896L;
    private String id;
    private String parentId;
    private String name;
    private List<TreeInfoDTO> children;

}
public class TestTreeUtils {
    public static void main(String[] args) {
        TreeInfoDTO treeInfoDTO = new TreeInfoDTO();
        treeInfoDTO.setId("0").setName("根");

        ArrayList<TreeInfoDTO> treeInfoDTOS = new ArrayList<>();
        TreeInfoDTO root = new TreeInfoDTO();
        root.setId("1");
        root.setParentId("0");
        root.setName("Root Node");

        List<TreeInfoDTO> levelOneNodes = new ArrayList<>();

        TreeInfoDTO node1 = new TreeInfoDTO();
        node1.setId("2");
        node1.setParentId("1");
        node1.setName("Node 1");

        TreeInfoDTO node2 = new TreeInfoDTO();
        node2.setId("3");
        node2.setParentId("1");
        node2.setName("Node 2");

        levelOneNodes.add(node1);
        levelOneNodes.add(node2);

        // root.setChildren(levelOneNodes);

        List<TreeInfoDTO> levelTwoNodes = new ArrayList<>();

        TreeInfoDTO node3 = new TreeInfoDTO();
        node3.setId("4");
        node3.setParentId("2");
        node3.setName("Node 1.1");

        TreeInfoDTO node4 = new TreeInfoDTO();
        node4.setId("5");
        node4.setParentId("2");
        node4.setName("Node 1.2");

        TreeInfoDTO node5 = new TreeInfoDTO();
        node5.setId("6");
        node5.setParentId("3");
        node5.setName("Node 2.1");

        levelTwoNodes.add(node3);
        levelTwoNodes.add(node4);
        levelTwoNodes.add(node5);

        // node1.setChildren(levelTwoNodes);

        TreeInfoDTO node6 = new TreeInfoDTO();
        node6.setId("7");
        node6.setParentId("3");
        node6.setName("Node 2.2");

        List<TreeInfoDTO> levelThreeNodes = new ArrayList<>();

        TreeInfoDTO node7 = new TreeInfoDTO();
        node7.setId("8");
        node7.setParentId("4");
        node7.setName("Node 1.1.1");

        TreeInfoDTO node8 = new TreeInfoDTO();
        node8.setId("9");
        node8.setParentId("5");
        node8.setName("Node 1.2.1");

        levelThreeNodes.add(node7);
        levelThreeNodes.add(node8);

        // node3.setChildren(levelThreeNodes);
        // node2.setChildren(Arrays.asList(node6));

        List<TreeInfoDTO> treeNodes = new ArrayList<>();
        treeNodes.add(root);
        treeNodes.add(node1);
        treeNodes.add(node2);
        treeNodes.add(node3);
        treeNodes.add(node4);
        treeNodes.add(node5);
        treeNodes.add(node6);
        treeNodes.add(node7);
        treeNodes.add(node8);
        List<Map<String,Object>> list = JSONObject.parseObject(JSONObject.toJSONString(treeNodes, SerializerFeature.WriteMapNullValue), List.class);
        List<Map<String, Object>> maps = TreeUtils.listToTree(list, "parentId", "id");
        List<TreeInfoDTO> treeInfoDTOS1 = JSONObject.parseArray(JSONObject.toJSONString(maps, SerializerFeature.WriteMapNullValue), TreeInfoDTO.class);
        treeInfoDTO.setChildren(treeInfoDTOS1);
        System.out.println(JSONObject.toJSONString(treeInfoDTO));

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 Java 工具类,可以将 List 换为树形结构: ```java import java.util.*; public class TreeUtil { public static <T extends TreeNode> List<T> buildTree(List<T> nodes) { if (nodes == null || nodes.size() == 0) { return Collections.emptyList(); } Map<Long, T> nodeMap = new HashMap<>(); for (T node : nodes) { nodeMap.put(node.getId(), node); } List<T> rootNodes = new ArrayList<>(); for (T node : nodes) { T parent = nodeMap.get(node.getParentId()); if (parent != null) { parent.addChild(node); } else { rootNodes.add(node); } } return rootNodes; } public interface TreeNode { Long getId(); Long getParentId(); void addChild(TreeNode child); List<? extends TreeNode> getChildren(); } } ``` 这个工具类包含了一个通用的接口 `TreeNode`,通过实现这个接口,可以将任意类型的 List 换为树形结构。 `TreeNode` 接口包含了三个方法: - `getId()`:获取节点的唯一标识符。 - `getParentId()`:获取节点的父节点标识符。 - `addChild(TreeNode child)`:将一个子节点添加到当前节点。 - `getChildren()`:获取当前节点的所有子节点。 使用这个工具类非常简单,只需要将需要换的 List 传入 `buildTree()` 方法中即可: ```java List<MyNode> nodes = ...; // 获取需要换的 List List<MyNode> rootNodes = TreeUtil.buildTree(nodes); ``` 其中 `MyNode` 是一个实现了 `TreeNode` 接口的自定义类。注意,为了能够正确地构建树形结构,每个节点的 `getParentId()` 方法必须返回其父节点的 `getId()` 值。否则,节点将无法正确地添加到树中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值