专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java递归将List数据转换为Tree结构数据_填坑指南

temp10 2024-10-03 01:22:03 java教程 12 ℃ 0 评论

背景

最近项目上有一个需求,在网页上的nav菜单需要展示成树形结构,还有很多数据也要展示树形结构,所以说需要封装一个公共方法来将对象List转为Tree树形数据结构。

挖坑

在第一次做的时候给自己挖了一个大坑,请先看代码

Java递归将List数据转换为Tree结构数据_填坑指南

public final List<Map<String, Object>> listToTree(String parentId, List<TaskEntity> list){
        List<Map<String, Object>> maps = new ArrayList<>();
        for (TaskEntity task : list){
            if (StringUtils.isBlank(parentId) && StringUtils.isBlank(task.getParentId())){
                Map<String, Object> map = JSON.parseObject(JSON.toJSONString(task), Map.class);
                map.put("children", listToTree(task.getId(), list));
                maps.add(map);
            } else if (StringUtils.isNotBlank(parentId) && StringUtils.isNotBlank(task.getParentId()) && parentId.equals(task.getParentId())){
                Map<String, Object> map = JSON.parseObject(JSON.toJSONString(task), Map.class);
                map.put("children", listToTree(task.getId(), list));
                maps.add(map);
            }
        }
        return maps;
    }

但是这种方法必须要传一个顶级数据的parentId,一般来说,最上级的数据parentId为null,直接调用这个方法传入parentId为null就可以,但是假如说我查询出一个list,但是这个list的没有最上级对象呢,那就不确定list中的哪个对象是最顶级,那这个parentId参数传什么呢?

填坑

首先讲一下思路,首先坑定是查出来一个list对象集合,然后找出list中最顶级的对象list,然后循环顶级list,然后找到list中含有parentId为当前循环到的顶级对象id的下一级对象List,加到当前循环的顶级对象的“children”属性中,children也是一个list集合,然后递归循环,直到取出所有数据转为Tree,下面看代码。

  • 对象List转为Tree树形结构的方法
	/**
     * 对象List转为Tree树形结构
     * @param entityList 数据List
     * @param parentFileName 用作上级ID的属性名
     * @return
     */
    public final List<Map<String, Object>> listToTree(List<T> entityList, String parentFileName){
        List<Map<String, Object>> mapList = new ArrayList<>();
        List<T> topList = getTopList(entityList, parentFileName);
        topList.forEach(entity -> {
            Map<String, Object> map = JSON.parseObject(JSON.toJSONString(entity, SerializerFeature.WriteMapNullValue), Map.class);
            if (!map.containsKey(parentFileName)) throw new NullPointerException("父级ID字段:" + parentFileName + " 不存在于对象中");
            map.put("children", getChildren(entity, entityList, parentFileName));
            mapList.add(map);
        });
        return mapList;
    }
  • 得到最顶级的数据List
	/**
     * 得到最顶级的数据List
     * @param entityList
     * @param parentFileName
     * @return
     */
    private final List<T> getTopList(List<T> entityList, String parentFileName){
        List<T> topList = new ArrayList<>();
        entityList.forEach(topEntity -> {
            AtomicBoolean isParent = new AtomicBoolean(true);
            Map<String, Object> topMap = JSON.parseObject(JSON.toJSONString(topEntity, SerializerFeature.WriteMapNullValue), Map.class);
            entityList.forEach(entity -> {
                if (!topMap.containsKey(parentFileName)) throw new NullPointerException("父级ID字段:" + parentFileName + " 不存在于对象中");
                if (entity.getId().equals(topMap.get(parentFileName))){
                    isParent.set(false);
                }
            });
            if (isParent.get()){
                topList.add(topEntity);
            }
        });
        return topList;
    }
  • 递归获取子级List,这里是个递归方法(方法中会调用这个方法本身)
private final List<Map<String, Object>> getChildren(T parent, List<T> entityList, String parentFileName){
        List<Map<String, Object>> mapList = new ArrayList<>();
        entityList.forEach(item -> {
            Map<String, Object> map = JSON.parseObject(JSON.toJSONString(item, SerializerFeature.WriteMapNullValue), Map.class);
            if (!map.containsKey(parentFileName)) throw new NullPointerException("父级ID字段:" + parentFileName + " 不存在于对象中");
            if (parent.getId().equals(map.get(parentFileName))){
                map.put("children", getChildren(item, entityList, parentFileName));
                mapList.add(map);
            }
        });
        return mapList;
    }

总结

  1. 具体实现思路就是:
  2. 得到最顶级对象List;
  3. 循环最顶级List并调用递归方法;
  4. 递归方法中在调用本身;
  5. 最后获得一个树形的Map集合。

注意

以上方法是封装在通用CRUD的service层的,项目中用到了MybatisPlus,然后继承MybatisPlus中的通用CRUD二次封装了一下,代码中的“T”为对象中的泛型,所以以上代码只是给大家提供一下思路,防止自己挖坑。方法可能无法直接使用到你的项目中,还是需要你自己看下,捋一捋思路的。祝你好运吧!!!

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表