java 递归返回树形组织结构(附带树形菜单的搜索)

简介: java 递归返回树形组织结构(附带树形菜单的搜索)

表结构

create table Project 
(
ID NUMBER not null,
NAME VARCHAR2(50),
PID NUMBER //父节点
)

实体

public class Project implements Serializable {
    private String Id;
    private String pId;
    private List<Project> childrenProjectList;
}

从一级往下递归组树

以下是Sqlserver的递归sql,mysql的话可以对应去查,原理是一样的,就是用sql查出所有树节点,然后存入hashmap(以pid为key,list为value),然后从一级项目去map里取,如果不想用递归sql,如果数据不多可以直接查出所有数据放入hashmap,如果数据多可以在java代码里循环查询数据库找出所有的节点(不推荐,频繁查库)

查询符合条件的数据和子节点

with subqry(Id,projectname,pid) as (
select id,projectname,pid from Project where ProjectManager = 'gehui'
union all
select Project.id,Project.projectname,Project.pid from Project,subqry
where Project.pid = subqry.id
)
select * from subqry;

查询符合条件的数据和父节点

with maco as
(
select * from Project where ProjectManager = 'gehui'
union all
select t.* from Project t,maco m where t.Id=m.pid
)
select * from maco order by ProjectManager

获取树节点

  projectSonList = projectMapper.selectSonProject(query);
            projectFatherList = projectMapper.selectFatherProject(query);
            projectFatherList.addAll(projectSonList);
            projectAllList = projectFatherList.stream().distinct().collect(Collectors.toList());

将节点放入hashmap

HashMap<String, List<Project>> ProjectMap= getProjectPidMap(projectAllList);
/**
     * 生成id为key的map
     *
     * @param projectFatherList
     * @return
     */
    public HashMap<String, List<Project>> getProjectIdMap(List<Project> projectFatherList) {
        HashMap<String, List<Project>> allProjectIdMap = new HashMap<>();
        //把所有的项目进行处理,用hashmap存储,以id为key,实体为value
        if (projectFatherList.size() != 0) {
            for (Project project : projectFatherList
            ) {
                // map中没有,并且不是父id不为空
                if (project.getId() != null) {
                    if (allProjectIdMap.get(project.getId()) == null) {
                        List<Project> projectLists = new ArrayList<>();
                        projectLists.add(project);
                        allProjectIdMap.put(project.getId(), projectLists);
                    } else {
                        allProjectIdMap.get(project.getId()).add(project);
                    }
                }
            }
        }
        return allProjectIdMap;
    }
  /**
     * 生成pid为key的map
     *
     * @param projectFatherList
     * @return
     */
    public HashMap<String, List<Project>> getProjectPidMap(List<Project> projectFatherList) {
        HashMap<String, List<Project>> allProjectIdMap = new HashMap<>();
        //把所有的项目进行处理,用hashmap存储,以id为key,实体为value
        if (projectFatherList.size() != 0) {
            for (Project project : projectFatherList
            ) {
                // map中没有,并且不是父id不为空
                if (project.getpId() != null) {
                    if (allProjectIdMap.get(project.getpId()) == null) {
                        List<Project> projectLists = new ArrayList<>();
                        projectLists.add(project);
                        allProjectIdMap.put(project.getpId(), projectLists);
                    } else {
                        allProjectIdMap.get(project.getpId()).add(project);
                    }
                }
            }
        }
        return allProjectIdMap;
    }

开始组树

 /**
     * 从一级向下递归
     *
     * @param projectFatherList
     * @return
     */
    public List<Project> getProjectTree(List<Project> projectFatherList, HashMap<String, List<Project>> allProjectMap) {
        //遍历,拿出所有的pidw为零的项目
        List<Project> firstLeaveProject = projectFatherList.stream().filter(project -> StringUtils.isEmpty(project.getpId())).collect(Collectors.toList());
        projectFatherList = getAllBottomProject(firstLeaveProject, allProjectMap);
        return projectFatherList;
    }

递归向下

 /**
     * 递归遍历此项目下所有项目
     *
     * @param leaveProjectList
     * @return
     */
    public List<Project> getAllBottomProject(List<Project> leaveProjectList, HashMap<String, List<Project>> allProjectMap) {
        if (leaveProjectList != null && leaveProjectList.size() != 0 && !allProjectMap.isEmpty()) {
            for (int i = leaveProjectList.size() - 1; i >= 0; i--) {
                if (leaveProjectList.get(i).getId() != null && allProjectMap.get(leaveProjectList.get(i).getId()) != null) {
                    leaveProjectList.get(i).setChildrenProjectList(allProjectMap.get(leaveProjectList.get(i).getId()));
                    //递归调用,查看子集是否还有子集
                    getAllBottomProject(leaveProjectList.get(i).getChildrenProjectList(), allProjectMap);
                }
            }
        }
        return leaveProjectList;
    }

树形菜单的搜索

根据筛选条件递归向上建树

/**
     * 递归向上建树
     *
     * @param leaveProjectList
     * @return
     */
    public List<Project> getAllProject(List<Project> leaveProjectList, List<Project> projectAllList, List<Project> projectLeaveFatherList) throws IOException, ClassNotFoundException {

        if (leaveProjectList != null && leaveProjectList.size() != 0) {
            for (Project project : leaveProjectList
            ) {
                List<Project> projectTempList = new LinkedList<>();
                List<Project> leaveProjectFatherList = new LinkedList<>();
                List<Project> leaveEqualsProject = new LinkedList<>();
                // 为每个元素找到父级树
                leaveProjectFatherList = projectAllList.stream().filter(e -> e.getId().equals(project.getpId())).collect(Collectors.toList());
                if (leaveProjectFatherList.size() > 0) {
                    // 把该元素放到父级树的子集树元素集中
                    leaveProjectFatherList.get(0).setChildrenProjectList(leaveEqualsProject);
                    leaveProjectFatherList.get(0).getChildrenProjectList().add(project);
                    leaveProjectFatherList.get(0).setHigh(project.getHigh() + Constant.ONE);
                    if (leaveProjectFatherList.get(0).getpId() != null) {
                        leaveProjectFatherList = getProject(leaveProjectFatherList, projectAllList);
                    }
                    if (leaveProjectFatherList.get(0) != null && leaveProjectFatherList.get(0).getpId() == null) {
                        projectLeaveFatherList.addAll(deepCopy(leaveProjectFatherList));
                    }
                } else {
                    projectTempList.add(project);
                    projectLeaveFatherList.addAll(deepCopy(projectTempList));
                }


            }

        }
        return projectLeaveFatherList;
    }

    public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteOut);
        out.writeObject(src);

        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
        ObjectInputStream in = new ObjectInputStream(byteIn);
        @SuppressWarnings("unchecked")
        List<T> dest = (List<T>) in.readObject();
        return dest;
    }


    public List<Project> getProject(List<Project> leaveProjectList, List<Project> projectAllList) {
        List<Project> leaveProjectFather;
        List<Project> leaveEquals = new LinkedList<>();
        if (leaveProjectList != null && leaveProjectList.size() != 0) {
            for (Project project : leaveProjectList
            ) {
                // 为每个元素找到父级树
                leaveProjectFather = projectAllList.stream().filter(e -> e.getId().equals(project.getpId())).collect(Collectors.toList());
                if (leaveProjectFather.size() > 0) {
                    // 把该元素放到父级树的子集树元素集中
                    leaveProjectFather.get(0).setChildrenProjectList(leaveEquals);
                    leaveProjectFather.get(0).getChildrenProjectList().add(project);
                    leaveProjectFather.get(0).setHigh(project.getHigh() + Constant.ONE);
                    leaveProjectList = leaveProjectFather;
                    leaveProjectList = getProject(leaveProjectList, projectAllList);
                }
            }
        }
        return leaveProjectList;
    }

总结

其实小编最喜欢的还是需要哪层返回哪层的数据,这样不需要递归,比如初始化只显示一级菜单,那么只返回一级菜单即可,点击再返回下一层

目录
相关文章
|
24天前
|
JSON Java 程序员
Java|如何用一个统一结构接收成员名称不固定的数据
本文介绍了一种 Java 中如何用一个统一结构接收成员名称不固定的数据的方法。
25 3
|
2月前
|
存储 算法 Java
🚀Java零基础-顺序结构详解 🚀
【10月更文挑战第11天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
39 6
|
3月前
|
Java
Java搜索与替换
Java搜索与替换
28 4
Java搜索与替换
|
3月前
|
Java
java基础(11)函数重载以及函数递归求和
Java支持函数重载,即在同一个类中可以声明多个同名方法,只要它们的参数类型和个数不同。函数重载与修饰符、返回值无关,但与参数的类型、个数、顺序有关。此外,文中还展示了如何使用递归方法`sum`来计算两个数之间的和,递归的终止条件是当第一个参数大于第二个参数时。
34 1
java基础(11)函数重载以及函数递归求和
|
2月前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
59 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
|
4月前
|
Java
Java应用结构规范问题之在UnitConvertUtils工具类将千米转换为米的问题如何解决
Java应用结构规范问题之在UnitConvertUtils工具类将千米转换为米的问题如何解决
|
4月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
|
4月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之配置Logback以在控制台输出日志的问题如何解决
Java应用结构规范问题之配置Logback以在控制台输出日志的问题如何解决
|
4月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
|
4月前
|
存储 开发者 C#
WPF与邮件发送:教你如何在Windows Presentation Foundation应用中无缝集成电子邮件功能——从界面设计到代码实现,全面解析邮件发送的每一个细节密武器!
【8月更文挑战第31天】本文探讨了如何在Windows Presentation Foundation(WPF)应用中集成电子邮件发送功能,详细介绍了从创建WPF项目到设计用户界面的全过程,并通过具体示例代码展示了如何使用`System.Net.Mail`命名空间中的`SmtpClient`和`MailMessage`类来实现邮件发送逻辑。文章还强调了安全性和错误处理的重要性,提供了实用的异常捕获代码片段,旨在帮助WPF开发者更好地掌握邮件发送技术,提升应用程序的功能性与用户体验。
75 0